Class: NoCms::Blocks::ActiveResourceSerializer

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

Overview

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

It uses the objects cache from the container in order to store the object and updates the _id field.

Instance Attribute Summary

Attributes inherited from BaseSerializer

#container, #field, #field_config

Instance Method Summary collapse

Methods inherited from BaseMultipleSerializer

#read_field, #write_field

Methods inherited from BaseSerializer

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

Constructor Details

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

Instance Method Details

#duplicateObject

We need to override this method for active resource in order to not find and save AR fields in blocks. When the field type is an ActiveRecord, it doesn’t matter, but with ActiveResource we have multiple errors in duplication time



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
# File 'app/serializers/no_cms/blocks/active_resource_serializer.rb', line 139

def duplicate
  dupped_value = case field_config[:duplicate]
    # When dupping we just dup the object and expect it has the right
    # behaviour. If it's nil we save nil (you can't dup NilClass)
    when :dup
      field_value = read
      field_value.nil? ? nil : field_value.dup
    # When nullifying we return nil
    when :nullify
      nil
    # when linking we return the same object
    when :link
      if field_config[:multiple]
        field_to_read = "#{field}_ids".to_sym
        field_ids = self.container.fields_info.symbolize_keys[field_to_read]
        field_ids.map{|id| field_config[:type].new(id: id)}
      else
        field_to_read = "#{field}_id".to_sym
        self.container.fields_info.symbolize_keys[field_to_read]
      end
  end
  write dupped_value

  # We need to clear cached objects when duplicate block because when it saves
  # it tries to save the cached objects. And we don't want this functionality when dup
  # in active record, because there is nothing to save

  self.container.cached_objects.clear
end

#read_multiple_fieldObject

If we don’t have the array of objects in the cache object we fetch it from the API 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.



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_resource_serializer.rb', line 45

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 API
  if field_ids.blank?
    []
  else
    values = field_config[:type].find_all(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 API using the id stored in the #BaseSerializer#field_id field.

If we don’t have the #BaseSerializer#field_id field then it builds (with build, 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.



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

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].build 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 ActiveResource objects.

When a hash comes with an id attribute then we get the object from the API 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.



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
# File 'app/serializers/no_cms/blocks/active_resource_serializer.rb', line 107

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 ActiveResource::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 ‘value` to be a Hash or an ActiveResource 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
93
# File 'app/serializers/no_cms/blocks/active_resource_serializer.rb', line 78

def write_single_field value
  case value
  when Hash
    resource = read
    value.each do |attribute_name, attribute_value|
      resource.send("#{attribute_name}=", attribute_value)
    end
  when ActiveResource::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
  end

  value
end