Module: Ardm::Ar::Relation

Extended by:
ActiveSupport::Concern
Defined in:
lib/ardm/ar/relation.rb

Constant Summary collapse

VALID_FIND_OPTIONS =

def apply_finder_options(options)

return super if options.nil? || options.empty?
options = options.dup
conditions = options.slice!(*::ActiveRecord::SpawnMethods::VALID_FIND_OPTIONS)
super(options).where(conditions)

end

[ :conditions, :include, :joins, :limit, :offset, :extend,
:order, :select, :readonly, :group, :having, :from, :lock ]

Instance Method Summary collapse

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(meth, *a, &b) ⇒ Object



66
67
68
69
70
# File 'lib/ardm/ar/relation.rb', line 66

def method_missing(meth, *a, &b)
  super
rescue => e
  raise NoMethodError, "Relation chain? #{self}.#{meth}\n#{e}"
end

Instance Method Details

#all(options = {}) ⇒ Object



72
73
74
# File 'lib/ardm/ar/relation.rb', line 72

def all(options={})
  apply_finder_options(options)
end

#apply_finder_options(options, *args) ⇒ Object

We used to just patch this, like above, but we need to copy it over completely for rails4 since it no longer supports the old style finder methods that act more like the datamapper finders.



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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
# File 'lib/ardm/ar/relation.rb', line 89

def apply_finder_options(options, *args)
  relation = clone
  return relation if options.nil?

  finders = options.dup
  finders[:select] = finders.delete(:fields)
  conditions = finders.slice!(*VALID_FIND_OPTIONS)

  finders.delete_if { |key, value| value.nil? && key != :limit }

  ([:joins, :select, :group, :order, :having, :limit, :offset, :from, :lock, :readonly] & finders.keys).each do |finder|
    relation = relation.send(finder, finders[finder])
  end

  conditions.each do |key, value|
    if assoc = relation.reflect_on_association(key)
      conditions.delete(key)
      # strip out assocations
      case assoc.macro
      when :belongs_to
        id = value.is_a?(Hash) ? value.with_indifferent_access[:id] : value
        relation = if value.is_a?(::ActiveRecord::Relation)
                     if value.values.empty?
                       relation.where.not(assoc.foreign_key => nil)
                     else
                       relation.where(assoc.foreign_key => value)
                     end
                   else
                     relation.where(assoc.foreign_key => id)
                   end
      when :has_one
        foreign_class = assoc.options[:class_name].constantize
        foreign_key   = assoc.foreign_key
        parent_key    = assoc.options[:child_key] || klass.primary_key

        if value.is_a?(::Array) && value.empty?
          # @fixme: dm basically no-ops cause it knows you are stupid
          return klass.where(klass.primary_key => nil)
        end

        relation = if value.is_a?(::ActiveRecord::Base)
                     relation.where(parent_key => value.send(assoc.foreign_key))
                   elsif value.is_a?(::ActiveRecord::Relation)
                     relation.where(parent_key => value.select(foreign_key))
                   elsif value.nil?
                     relation.where.not(parent_key => foreign_class.select(foreign_key).where.not(foreign_key => value))
                   else
                     relation.where(parent_key => foreign_class.select(foreign_key).where(value))
                   end
      when :has_many
        foreign_class = assoc.options[:class_name].constantize
        foreign_key   = assoc.foreign_key
        parent_key    = assoc.options[:child_key] || klass.primary_key

        relation = if value.is_a?(::ActiveRecord::Relation)
                     relation.where(foreign_key => value)
                   else
                     relation.where(parent_key => foreign_class.select(foreign_class.primary_key).where.not(foreign_key => value))
                   end
      else
        raise("unknown: #{assoc.inspect}")
      end
    end
  end

  processed_conditions = {}

  conditions.each do |key, value|
    key = key.is_a?(Ardm::Property) ? key.name : key

    case key
    when String, Symbol then
      processed_conditions[key] = value
    when Ardm::Query::Operator then
      relation = key.to_arel(self, value).scope
    else raise "unknown key: #{key.inspect} #{value.inspect}"
    end
  end

  relation = relation.where(processed_conditions) if processed_conditions.any?
  relation = relation.where(finders[:conditions]) if options.has_key?(:conditions)
  relation = relation.includes(finders[:include]) if options.has_key?(:include)
  relation = relation.extending(finders[:extend]) if options.has_key?(:extend)

  relation
end

#calculate(operation, column_name, options = {}) ⇒ Object



177
178
179
180
181
182
# File 'lib/ardm/ar/relation.rb', line 177

def calculate(operation, column_name, options={})
  if property = properties[column_name]
    column_name = property.field
  end
  super(operation, column_name, options)
end

#destroy!Object



197
198
199
# File 'lib/ardm/ar/relation.rb', line 197

def destroy!
  delete_all
end