module RelationBuilder::InitializeOptions
Private Instance Methods
build_relation_with_options(rel, options = {})
click to toggle source
Build relation based on type of it
# File lib/relation_builder/initialize_options.rb, line 55 def build_relation_with_options(rel, options = {}) reflection = reflection_for(rel) if reflection.present? relation = instance_eval(rel.to_s) if %i(has_and_belongs_to_many has_many references_and_referenced_in_many references_many).include?(reflection.macro) if relation.blank? relation << reflection.klass.new({}, options) end else if relation.blank? self.send("#{rel}=", reflection.klass.new({}, options)) end end end end
create_nested_options(build_options)
click to toggle source
Create nested Hash with attributes for using in nested_attributes Example:
input: {versions: {doc_kit_source: [:source, :author]}, product: :project} Output: {versions_attributes: {doc_kit_source_attributes: {source_attributes: {}, author_attributes: {} } }, product_attributes: {project_attributes: {}} }
# File lib/relation_builder/initialize_options.rb, line 89 def create_nested_options(build_options) new_attributes = {} if build_options.is_a?(Hash) build_options.each do |required_rel, nested_rels| new_attributes.merge!(rel_name_to_nested_attrs(required_rel)) nested_key = to_nested_attributes_key(required_rel) if nested_rels.is_a?(Symbol) new_attributes[nested_key].merge!(rel_name_to_nested_attrs(nested_rels)) elsif nested_rels.is_a?(Array) nested_rels.each do |nested_rel| new_attributes[nested_key].merge!(rel_name_to_nested_attrs(nested_rel)) end elsif nested_rels.is_a?(Hash) new_attributes[nested_key].merge!(create_nested_options(nested_rels)) end end end new_attributes end
initialize_with_build_relation(new_attributes = nil, options = {})
click to toggle source
Chain initialize method for support additional options
# File lib/relation_builder/initialize_options.rb, line 12 def initialize_with_build_relation(new_attributes = nil, options = {}) # relation build strategy: # nested - using nested_attributes # build - using standard build method nested_build_strategy = options[:build_strategy] || :nested processed_attributes = new_attributes || {} auto_build_relation_list = options.delete(:auto_build_relations) if nested_build_strategy == :nested && auto_build_relation_list.present? nested_relations_attributes = create_nested_options(auto_build_relation_list) processed_attributes = nested_deep_merge(processed_attributes, nested_relations_attributes) end # store return value to save default behaviour of initialize ret_val = initialize_without_build_relation(processed_attributes, options) if nested_build_strategy == :build && auto_build_relation_list.present? if auto_build_relation_list.is_a?(Array) auto_build_relation_list.each do |rel| build_relation_with_options(rel) end elsif auto_build_relation_list.is_a?(Hash) auto_build_relation_list.each do |rel, nested_options| build_relation_with_options(rel, auto_build_relations: nested_options) end elsif auto_build_relation_list.is_a?(Symbol) || auto_build_relation_list.is_a?(String) build_relation_with_options(auto_build_relation_list) end end ret_val end
key_is_numeric?(key)
click to toggle source
# File lib/relation_builder/initialize_options.rb, line 148 def key_is_numeric?(key) !(key =~ /^\d+$/).nil? end
nested_deep_merge(master, slave)
click to toggle source
Merge of initialize params and additional options for build relations through nested_attributes
# File lib/relation_builder/initialize_options.rb, line 121 def nested_deep_merge(master, slave) # Add alternative deep_merge method for instance of Hash extend_deep_merge = ->(obj){obj.send(:extend, RelationBuilder::ExtDeepMerge) unless master.is_a? RelationBuilder::ExtDeepMerge; obj} extend_deep_merge.call(master) extend_deep_merge.call(slave) # extend_deep_merge call block for any coincide keys master.ext_deep_merge(slave) do |_, master_val, slave_val| # special processing of attributes for has_many relation (see nested_attributes documentation for details) if master_val.is_a?(Hash) && master_val.all?{|k, _| key_is_numeric?(k)} extend_deep_merge.call(master_val) master_val.inject(extend_deep_merge.call({})) do |h, (inner_key, value)| h[inner_key] = nested_deep_merge(value, slave_val) h end elsif master_val.is_a?(Hash) && slave_val.is_a?(Hash) extend_deep_merge.call(master_val) extend_deep_merge.call(slave_val) nested_deep_merge(master_val, slave_val) else master_val end end end
reflection_for(method)
click to toggle source
Get onformation about relation
# File lib/relation_builder/initialize_options.rb, line 46 def reflection_for(method) if self.class.respond_to?(:reflect_on_association) self.class.reflect_on_association(method) elsif self.class.respond_to?(:associations) # MongoMapper uses the 'associations(method)' instead self.class.associations[method] end end
rel_name_to_nested_attrs(relation_name)
click to toggle source
Hash for passing into nested_attributes for build single relation
# File lib/relation_builder/initialize_options.rb, line 116 def rel_name_to_nested_attrs(relation_name) {to_nested_attributes_key(relation_name) => {}} end
to_nested_attributes_key(relation_name)
click to toggle source
Generate key-name for nested_attributes from relation name
# File lib/relation_builder/initialize_options.rb, line 111 def to_nested_attributes_key(relation_name) "#{relation_name}_attributes".to_sym end