Module: Globalize::ActiveRecord::ClassMethods

Defined in:
lib/globalize/active_record/class_methods.rb

Instance Method Summary collapse

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method_id, *arguments, &block) ⇒ Object


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
# File 'lib/globalize/active_record/class_methods.rb', line 85

def method_missing(method_id, *arguments, &block)
  match, attribute_names, translated_attributes, untranslated_attributes = supported_on_missing?(method_id)
  return super unless match

  scope = scoped

  translated_attributes.each do |attr|
    scope = scope.with_translated_attribute(attr, arguments[attribute_names.index(attr)])
  end

  untranslated_attributes.each do |unt|
    index = attribute_names.index(unt)
    raise StandarError unless index
    scope = scope.send(:"scoped_by_#{unt}", arguments[index])
  end

  if defined?(::ActiveRecord::DynamicFinderMatch) && match.is_a?(::ActiveRecord::DynamicFinderMatch)
    if match.instantiator? and scope.blank?
      return scope.find_or_instantiator_by_attributes match, attribute_names, *arguments, &block
    end
    match_finder_method = match.finder.to_s
    match_finder_method << "!" if match.bang? && ::ActiveRecord::VERSION::STRING >= "3.1.0"
    return scope.send(match_finder_method).tap do |found|
      found.is_a?(Array) ? found.map { |f| f.translations.reload } : found.translations.reload unless found.nil?
    end
  end
  return scope
end

Instance Method Details

#find_or_instantiator_by_attributes(match, attributes, *args) {|record| ... } ⇒ Object

Yields:

  • (record)

114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/globalize/active_record/class_methods.rb', line 114

def find_or_instantiator_by_attributes(match, attributes, *args)
  options = args.size > 1 && args.last(2).all?{ |a| a.is_a?(Hash) } ? args.extract_options! : {}
  protected_attributes_for_create, unprotected_attributes_for_create = {}, {}
  args.each_with_index do |arg, i|
    if arg.is_a?(Hash)
      protected_attributes_for_create = args[i].with_indifferent_access
    else
      unprotected_attributes_for_create[attributes[i]] = args[i]
    end
  end

  record = if ::ActiveRecord::VERSION::STRING < "3.1.0"
    new do |r|
      r.send(:attributes=, protected_attributes_for_create, true) unless protected_attributes_for_create.empty?
      r.send(:attributes=, unprotected_attributes_for_create, false) unless unprotected_attributes_for_create.empty?
    end
  else
    new(protected_attributes_for_create, options) do |r|
      r.assign_attributes(unprotected_attributes_for_create, :without_protection => true)
    end
  end
  yield(record) if block_given?
  record.send(match.bang? ? :save! : :save) if match.instantiator.eql?(:create)

  record
end

#required_attributesObject


33
34
35
# File 'lib/globalize/active_record/class_methods.rb', line 33

def required_attributes
  validators.map { |v| v.attributes if v.is_a?(ActiveModel::Validations::PresenceValidator) }.flatten
end

#required_translated_attributesObject


37
38
39
# File 'lib/globalize/active_record/class_methods.rb', line 37

def required_translated_attributes
  translated_attribute_names & required_attributes
end

#respond_to?(method_id, *args, &block) ⇒ Boolean

Returns:

  • (Boolean)

62
63
64
# File 'lib/globalize/active_record/class_methods.rb', line 62

def respond_to?(method_id, *args, &block)
  supported_on_missing?(method_id) || super
end

#respond_to_missing?(method_id, include_private = false) ⇒ Boolean

Returns:

  • (Boolean)

66
67
68
# File 'lib/globalize/active_record/class_methods.rb', line 66

def respond_to_missing?(method_id, include_private = false)
  supported_on_missing?(method_id) || super
end

#supported_on_missing?(method_id) ⇒ Boolean

Returns:

  • (Boolean)

71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/globalize/active_record/class_methods.rb', line 71

def supported_on_missing?(method_id)
  return super unless RUBY_VERSION < '1.9' || respond_to?(:translated_attribute_names)
  match = defined?(::ActiveRecord::DynamicFinderMatch) && (::ActiveRecord::DynamicFinderMatch.match(method_id) || ::ActiveRecord::DynamicScopeMatch.match(method_id))
  return false if match.nil?

  attribute_names = match.attribute_names.map(&:to_sym)
  translated_attributes = attribute_names & translated_attribute_names
  return false if translated_attributes.empty?

  untranslated_attributes = attribute_names - translated_attributes
  return false if untranslated_attributes.any?{|unt| ! respond_to?(:"scoped_by_#{unt}")}
  return [match, attribute_names, translated_attributes, untranslated_attributes]
end

#translated?(name) ⇒ Boolean

Returns:

  • (Boolean)

29
30
31
# File 'lib/globalize/active_record/class_methods.rb', line 29

def translated?(name)
  translated_attribute_names.include?(name.to_sym)
end

#translated_column_name(name) ⇒ Object


57
58
59
# File 'lib/globalize/active_record/class_methods.rb', line 57

def translated_column_name(name)
  "#{translation_class.table_name}.#{name}"
end

#translation_classObject


41
42
43
44
45
46
47
48
49
50
51
# File 'lib/globalize/active_record/class_methods.rb', line 41

def translation_class
  @translation_class ||= begin
    klass = self.const_get(:Translation) rescue nil
    if klass.nil? || klass.class_name != (self.class_name + "Translation")
      klass = self.const_set(:Translation, Class.new(Globalize::ActiveRecord::Translation))
    end

    klass.belongs_to :globalized_model, :class_name => self.name, :foreign_key => translation_options[:foreign_key]
    klass
  end
end

#translations_table_nameObject


53
54
55
# File 'lib/globalize/active_record/class_methods.rb', line 53

def translations_table_name
  translation_class.table_name
end

#with_locales(*locales) ⇒ Object


6
7
8
# File 'lib/globalize/active_record/class_methods.rb', line 6

def with_locales(*locales)
  scoped.merge(translation_class.with_locales(*locales))
end

#with_required_attributesObject


15
16
17
18
19
# File 'lib/globalize/active_record/class_methods.rb', line 15

def with_required_attributes
  required_translated_attributes.inject(scoped) do |scope, name|
    scope.where("#{translated_column_name(name)} IS NOT NULL")
  end
end

#with_translated_attribute(name, value, locales = nil) ⇒ Object


21
22
23
24
25
26
27
# File 'lib/globalize/active_record/class_methods.rb', line 21

def with_translated_attribute(name, value, locales = nil)
  locales ||= Globalize.fallbacks
  with_translations.where(
    translated_column_name(name)    => value,
    translated_column_name(:locale) => Array(locales).map(&:to_s)
  )
end

#with_translations(*locales) ⇒ Object


10
11
12
13
# File 'lib/globalize/active_record/class_methods.rb', line 10

def with_translations(*locales)
  locales = translated_locales if locales.empty?
  includes(:translations).with_locales(locales).with_required_attributes
end