Class: NoCms::Blocks::ActiveRecordSerializer

Inherits:
BaseMultipleSerializer show all
Defined in:
app/serializers/no_cms/blocks/active_record_serializer.rb

Overview

This class implements the read/write behaviour for ActiveRecord fields.

It uses the objects cache from the container in order to store the objectand update the _id field.

Instance Attribute Summary

Attributes inherited from BaseSerializer

#container, #field, #field_config

Instance Method Summary collapse

Methods inherited from BaseMultipleSerializer

#duplicate, #read_field, #write_field

Methods inherited from BaseSerializer

#duplicate, #initialize, #read, #read_field, #write, #write_field

Constructor Details

This class inherits a constructor from NoCms::Blocks::BaseSerializer

Instance Method Details

#read_multiple_fieldObject

If we don’t have the array of objects in the cache object we fetch it from the database using the id stored in the #BaseSerializer#field_ids field.

If we don’t have the #BaseSerializer#field_ids field or it’s blank then it returns an empty array.



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'app/serializers/no_cms/blocks/active_record_serializer.rb', line 44

def read_multiple_field

  # We get and return the objects from the cached objects
  values = self.container.cached_objects[self.field.to_sym]
  return values if values

  # If there was nothing in the cache then we try to get the object ids
  field_ids = self.container.fields_info.symbolize_keys["#{field}_ids".to_sym]

  # Hstore serializes every field as a string, so we have to turn "[1, 2]"
  # to an actual array of integers
  if NoCms::Blocks.database_serializer == :hstore
    field_ids = field_ids.gsub(/[\[\]]/, '').split(',').map(&:to_i)
  end

  # If there's any id we try to get them from the database
  if field_ids.blank?
    []
  else
    values = field_config[:type].where(id: field_ids)
    self.container.cached_objects[field.to_sym] = values
  end

end

#read_single_fieldObject

If the field is not present in our objects cache we fetch it from the database using the id stored in the #BaseSerializer#field_id field.

If we don’t have the #BaseSerializer#field_id field then it builds (with new, not with create) a new one and stores it in the objects cache. Later, if the block is saved, this object will be saved too.



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'app/serializers/no_cms/blocks/active_record_serializer.rb', line 17

def read_single_field
  # We get and return the object from the cached objects
  value = self.container.cached_objects[self.field.to_sym]
  return value if value

  # If there was nothing in the cache then we try to get the object id and
  # find the object in the database
  field_id = self.container.fields_info.symbolize_keys["#{field}_id".to_sym]

  # Hstore serializes every field as a string, so we have to turn it into an
  # integer
  field_id = field_id.to_i if field_id.present? && NoCms::Blocks.database_serializer == :hstore

  value = field_config[:type].find(field_id) unless field_id.blank?

  # If we still don't have any object then we build a new one
  value = field_config[:type].new if value.nil?

  self.container.cached_objects[field.to_sym] = value
end

#write_multiple_field(values) ⇒ Object

This method expects ‘value` to be an array of Hashes or ActiveRecord objects.

When a hash comes with an id attribute then we get the object from the database and assign it the attributes. In other case we create a new record.

When an object (or nil) is in the array we just get it.

Then we get all the objects in the objects cache and save the ids in the ids field.



106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'app/serializers/no_cms/blocks/active_record_serializer.rb', line 106

def write_multiple_field values
  raise ArgumentError.new "Array expected for #{field} attribute" unless values.is_a? Array

  self.container.cached_objects[field.to_sym] = values.map do |value|
    case value
    when Hash
      if value.has_key? :id
        object = field_config[:type].find(value[:id])
        object.assign_attributes value
        object
      else
        field_config[:type].new value
      end
    when ActiveRecord::Base, nil
      value
    else
      raise ArgumentError.new "Hash, ActiveRecord or nil expected for #{field} attribute"
    end
  end

  self.container.fields_info["#{field}_ids".to_sym] = self.container.cached_objects[field.to_sym].map(&:id)

end

#write_single_field(value) ⇒ Object

This method expects ‘value` to be a Hash or an ActiveRecord object.

When ‘value` is a Hash we load the object and assign the hash through an assign_attributes. This solves the scenario of a nested form where a hash is passed as the value of the field.

When ‘value` is an object (or nil) we save it in the object’s cache and overwrite the _id field



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'app/serializers/no_cms/blocks/active_record_serializer.rb', line 78

def write_single_field value
  case value
  when Hash
    read_single_field.assign_attributes value
  when ActiveRecord::Base, nil
    # We save in the objects cache the new value
    self.container.cached_objects[field.to_sym] = value
    # and then we store the new id in the fields_info hash
    self.container.fields_info["#{field}_id".to_sym] = value.nil? ? nil : value.id
  else
    raise ArgumentError.new "Hash, ActiveRecord or nil expected for #{field} attribute"
  end

  value
end