app/models/no_cms/blocks/block.rb in nocms-blocks-1.0.0 vs app/models/no_cms/blocks/block.rb in nocms-blocks-1.1.0
- old
+ new
@@ -7,154 +7,57 @@
scope :drafts, ->() { where_with_locale(draft: true) }
scope :no_drafts, ->() { where_with_locale(draft: false) }
scope :roots, ->() { where parent_id: nil }
- accepts_nested_attributes_for :children, allow_destroy: true
+ translates :draft
+ include NoCms::Blocks::Concerns::SerializingFields
- attr_reader :cached_objects
-
- translates :layout, :fields_info, :draft
- accepts_nested_attributes_for :translations
-
- class Translation
- serialize :fields_info, Hash
+ ##
+ # In the block we get all the fields so it can accept all of them
+ def fields_configuration
+ layout_config.fields
end
- after_initialize :set_blank_fields
- before_save :save_related_objects
-
- validates :fields_info, presence: { allow_blank: true }
validates :layout, presence: true
- def cache_enabled
- layout_config.has_key?(:cache_enabled) ? layout_config[:cache_enabled] : NoCms::Blocks.cache_enabled
- end
+ ##
+ # A block dups all it's children and the translations
+ def duplicate_self new_self
+ new_self.translations = translations.map(&:dup)
+ new_self.translations.each { |t| t.globalized_model = new_self }
- def layout_config
- NoCms::Blocks.block_layouts.stringify_keys[layout]
- end
-
- def template
- layout_config[:template] if layout_config
- end
-
- def has_field? field
- # We have the field if...
- !layout_config.nil? && # We have a layout configuration AND
- (
- !layout_config[:fields].symbolize_keys[field.to_sym].nil? || # We have this field OR
- !layout_config[:fields].symbolize_keys[field.to_s.gsub(/\_id$/, '').to_sym].nil? # we remove the final _id and then we have the field
- )
- end
-
- def field_type field
- return nil unless has_field?(field)
- layout_config[:fields].symbolize_keys[field.to_sym]
- end
-
- def read_field field
- return nil unless has_field?(field)
-
- value = fields_info[field.to_sym] || # first, we get the value
- @cached_objects[field.to_sym] # or we get it from the cached objects
-
- # If value is still nil, but the field exists we must get the object from the database
- if value.nil?
- field_type = field_type(field)
- field_id = fields_info["#{field}_id".to_sym]
- value = @cached_objects[field.to_sym] = field_type.find(field_id) unless field_id.nil?
+ children.each do |child|
+ new_self.children << child.dup
end
-
- # If value is still nil, and the field_type is an ActiveRecord class, then we
- if value.nil? && field_type.is_a?(Class)
- value = @cached_objects[field.to_sym] = field_type.new
- end
- value
end
- def write_field field, value
- return nil unless has_field?(field)
- field_type = field_type field
- # If field type is a model then we update the cached object
- if field_type.is_a?(Class) && field_type < ActiveRecord::Base
- # First, we initialize the object if we don't read the object (it loads it into the cached objects)
- @cached_objects[field.to_sym] = field_type.new if read_field(field).nil?
- # Then, assign attributes
- @cached_objects[field.to_sym].assign_attributes value
- else # If it's a model then a new object or update the previous one
- self.fields_info = fields_info.merge field.to_sym => value # when updating through an object (i.e. the page updates through nested attributes) fields_info[field.to_sym] = value doesn't work. Kudos to Rubo for this fix
- end
- end
+ class Translation
- # In this missing method we check wether we're asking for one field
- # in which case we will read or write ir
- def method_missing(m, *args, &block)
- # We get the name of the field stripping out the '=' for writers
- field = m.to_s
- write_accessor = field.ends_with? '='
- field.gsub!(/\=$/, '')
-
- # If this field actually exists, then we write it or read it.
- if has_field?(field)
- write_accessor ?
- write_field(field, args.first) :
- read_field(field.to_sym)
- else
- super
+ ##
+ # In the translation we get only the translated fields
+ def fields_configuration
+ layout_config.translated_fields
end
- end
- # When we are assigning attributes (this method is called in new, create...)
- # we must split those fields from our current layout and those who are not
- # (they must be attributes).
- # Attributes are processed the usual way and fields are written later
- def assign_attributes new_attributes
- fields = []
+ ##
+ # Sometimes the translation still won't have the globalized_model linked
+ # (e.g. before it's saved for the first time) and we must have a mechanism
+ # to be able to store a temporary layout
+ attr_accessor :layout
- set_blank_fields
-
- # We get the layout
- new_layout = new_attributes[:layout] || new_attributes['layout']
- self.layout = new_layout unless new_layout.nil?
-
- Rails.logger.info "Searching #{new_attributes.keys.inspect} fields in #{self.layout} layout"
-
- # And now separate fields and attributes
- fields = new_attributes.select{|k, _| has_field? k }.symbolize_keys
- new_attributes.reject!{|k, _| has_field? k }
-
- super(new_attributes)
-
- Rails.logger.info "Writing #{fields.inspect} to #{self.layout} block"
-
- fields.each do |field_name, value|
- self.write_field field_name, value
+ ##
+ # If we don't have a globalized model yet we return our temporary layout
+ def layout
+ globalized_model.nil? ? @layout : globalized_model.layout
end
- end
- def reload *args
- @cached_objects = {}
- super
+ include NoCms::Blocks::Concerns::SerializingFields
end
- private
+ accepts_nested_attributes_for :children, allow_destroy: true
+ accepts_nested_attributes_for :translations
- def set_blank_fields
- self.fields_info ||= {}
- @cached_objects ||= {}
- end
-
- def save_related_objects
- # Now we save each activerecord related object
- cached_objects.each do |field, object|
- # Notice that we don't care if the object is actually saved
- # We don't care because there may be some cases where no real information is sent to an object but something is sent (i.e. the locale in a new Globalize translation) and then the object is created empty
- # When this happens if we save! the object an error is thrown and we can't leave the object blank
- if object.is_a?(ActiveRecord::Base) && object.save
- fields_info["#{field}_id".to_sym] = object.id
- end
- end
- end
end
+
end