Module: Netzke::ActiveRecord::Attributes

Extended by:
ActiveSupport::Concern
Defined in:
lib/netzke/active_record/attributes.rb

Defined Under Namespace

Modules: ClassMethods

Instance Method Summary collapse

Instance Method Details

#netzke_array(attributes = self.class.netzke_attributes) ⇒ Object

Transforms a record to array of values according to the passed attributes



149
150
151
152
153
154
155
156
# File 'lib/netzke/active_record/attributes.rb', line 149

def netzke_array(attributes = self.class.netzke_attributes)
  res = []
  for a in attributes
    next if a[:included] == false
    res << value_for_attribute(a, a[:nested_attribute])
  end
  res
end

#netzke_hash(attributes = self.class.netzke_attributes) ⇒ Object

Accepts both hash and array of attributes



163
164
165
166
167
168
169
170
# File 'lib/netzke/active_record/attributes.rb', line 163

def netzke_hash(attributes = self.class.netzke_attributes)
  res = {}
  for a in (attributes.is_a?(Hash) ? attributes.values : attributes)
    next if a[:included] == false
    res[a[:name].to_sym] = self.value_for_attribute(a, a[:nested_attribute])
  end
  res
end

#netzke_jsonObject



158
159
160
# File 'lib/netzke/active_record/attributes.rb', line 158

def netzke_json
  netzke_hash.to_nifty_json
end

#set_value_for_attribute(a, v) ⇒ Object

Assigns new value to an (association) attribute



204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
# File 'lib/netzke/active_record/attributes.rb', line 204

def set_value_for_attribute(a, v)
  v = v.to_time_in_current_zone if v.is_a?(Date) # convert Date to Time

  if a[:setter]
    a[:setter].call(self, v)
  elsif respond_to?("#{a[:name]}=")
    send("#{a[:name]}=", v)
  elsif is_association_attr?(a)
    split = a[:name].to_s.split(/\.|__/)
    if a[:nested_attribute]
      # We want:
      #     set_value_for_attribute({:name => :assoc_1__assoc_2__method, :nested_attribute => true}, 100)
      # =>
      #     self.assoc_1.assoc_2.method = 100
      split.inject(self) { |r,m| m == split.last ? (r && r.send("#{m}=", v) && r.save) : r.send(m) }
    else
      if split.size == 2
        # search for association and assign it to self
        assoc = self.class.reflect_on_association(split.first.to_sym)
        assoc_method = split.last
        if assoc
          if assoc.macro == :has_one
            assoc_instance = self.send(assoc.name)
            if assoc_instance
              assoc_instance.send("#{assoc_method}=", v)
              assoc_instance.save # what should we do when this fails?..
            else
              # what should we do in this case?
            end
          else
            self.send("#{assoc.options[:foreign_key] || assoc.name.to_s.foreign_key}=", v)
          end
        else
          logger.debug "Netzke::Basepack: Association #{assoc} is not known for class #{self.class.name}"
        end
      else
        logger.debug "Netzke::Basepack: Wrong attribute name: #{a[:name]}"
      end
    end
  end
end

#value_for_attribute(a, through_association = false) ⇒ Object

Fetches the value specified by an (association) attribute If through_association is true, get the value of the association by provided method, not the associated record’s id E.g., author__name with through_association set to true may return “Vladimir Nabokov”, while with through_association set to false, it’ll return author_id for the current record



175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
# File 'lib/netzke/active_record/attributes.rb', line 175

def value_for_attribute(a, through_association = false)
  v = if a[:getter]
    a[:getter].call(self)
  elsif respond_to?("#{a[:name]}")
    send("#{a[:name]}")
  elsif is_association_attr?(a)
    split = a[:name].to_s.split(/\.|__/)
    assoc = self.class.reflect_on_association(split.first.to_sym)
    if through_association
      split.inject(self) do |r,m| # TODO: do we really need to descend deeper than 1 level?
        if r.respond_to?(m)
          r.send(m)
        else
          logger.debug "Netzke::Basepack: Wrong attribute name: #{a[:name]}" unless r.nil?
          nil
        end
      end
    else
      self.send("#{assoc.options[:foreign_key] || assoc.name.to_s.foreign_key}")
    end
  end

  # a work-around for to_json not taking the current timezone into account when serializing ActiveSupport::TimeWithZone
  v = v.to_datetime.to_s(:db) if [ActiveSupport::TimeWithZone].include?(v.class)

  v
end