Module: TranslateColumns::ClassMethods

Defined in:
lib/translate_columns.rb

Overview

methods used in the class definition

Instance Method Summary collapse

Instance Method Details

#translate_columns(*options) ⇒ Object

Read the provided list of symbols as column names and generate methods for each to access translated versions.

Possible options, after the columns, include:

  • :locale_field - Name of the field in the parents translation table

of the locale. This defaults to ‘locale’.



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/translate_columns.rb', line 27

def translate_columns( *options )
   
  locale_field = 'locale'
  
  columns = [ ]
  if ! options.is_a? Array
    raise "Provided parameter to translate_columns is not an array!"
  end
  # extract all the options
  options.each do | opt |
    if opt.is_a? Symbol
      columns << opt
    elsif opt.is_a? Hash
      # Override the locale class if set.
      locale_field = opt[:locale_field]
    end
  end

  define_method 'columns_to_translate' do
    columns.collect{ |c| c.to_s }
  end
  
  # set the instance Methods first
  include TranslateColumns::InstanceMethods
  
  # Rails magic to override the normal save process
  alias_method_chain :save, :translation
  alias_method_chain :save!, :translation
  alias_method_chain :attributes=, :locale

  # Generate a module containing methods that override access 
  # to the ActiveRecord methods.
  # This dynamic module is then included in the parent such that
  # the super method will function correctly.
  mod = Module.new do | m |
    
    columns.each do | column |

      next if ['id', locale_field].include?(column.to_s)
    
      # This is strange, so allow me to explain:
      #  We define access to the original method and its super,
      #  a normal "alias" can't find the super which is the method
      #  created by ActionBase.
      #  The Alias_method function takes a copy, and retains the 
      #  ability to call the parent with the same name.
      #  Finally, the method is overwritten to support translation.
      #  
      #  All this is to avoid defining parameters for the overwritten
      #  accessor which normally doesn't have them.
      #  (Warnings are produced on execution when a metaprogrammed
      #  function is called without parameters and its expecting them)
      #  
      #  Sam Lown (2007-01-17) dev at samlown dot com
      define_method(column) do
        # This super should call the missing_method method in ActiveRecord.
        super()
      end
      
      alias_method("#{column}_before_translation", column)
      
      # overwrite accessor to read
      define_method("#{column}") do
        if translation and ! translation.send(column).blank?
          translation.send(column)
        else
          super()
        end
      end
      
      define_method("#{column}_before_type_cast") do 
        if (translation)
          translation.send("#{column}_before_type_cast")
        else
          super()
        end
      end
      
      define_method("#{column}=") do |value|
        # translation object must have already been set up for this to work!
        if (translation)
          translation.send("#{column}=",value)
        else
          super( value )
        end  
      end          

    end
  end # dynamic module

  # include the anonymous module so that the "super" method
  # will work correctly in the child!
  include mod
end