Module: DataMapper::NestedAttributes::ClassMethods
- Defined in:
- lib/dm-accepts_nested_attributes/nested_attributes.rb
Class Method Summary collapse
Instance Method Summary collapse
-
#accepts_nested_attributes_for(association_name, options = {}) ⇒ Object
Defines an attributes reader and writer for the specified association(s).
-
#associated_model_for_name(association_name, repository = :default) ⇒ Object
i have the feeling this should be refactored.
-
#association_for_name(name, repository = :default) ⇒ Object
avoid nil access by always going through this this method raises if the association named name is not established in this model.
-
#association_type(association_name) ⇒ Object
maybe this should be provided by dm-core somehow DataMapper::Association::Relationship would be a place maybe?.
-
#nr_of_possible_child_instances(association_name, repository = :default) ⇒ Object
utility methods.
- #reject_new_nested_attributes_proc_for(association_name) ⇒ Object
Class Method Details
.extended(base) ⇒ Object
6 7 8 9 |
# File 'lib/dm-accepts_nested_attributes/nested_attributes.rb', line 6 def self.extended(base) base.class_inheritable_accessor :autosave_associations base.autosave_associations = {} end |
Instance Method Details
#accepts_nested_attributes_for(association_name, options = {}) ⇒ Object
Defines an attributes reader and writer for the specified association(s). If you are using attr_protected or attr_accessible, then you will need to add the attribute writer to the allowed list.
After any params are passed to the attributes writer they are available via the attributes reader (they are stored in an instance variable of the same name). The attributes reader returns nil if the attributes writer has not been called.
Supported options:
- :allow_destroy
-
If true, destroys any members from the attributes hash with a
_deletekey and a value that evaluates totrue(eg. 1, ‘1’, true, or ‘true’). This option is off by default.- :reject_if
-
Allows you to specify a Proc that checks whether a record should be built for a certain attribute hash. The hash is passed to the Proc and the Proc should return either
trueorfalse. When no Proc is specified a record will be built for all attribute hashes that do not have a_deletethat evaluates to true.Examples: # creates avatar_attributes # creates avatar_attributes= accepts_nested_attributes_for :avatar, :reject_if => proc { |attributes| attributes.blank? } # creates avatar_attributes and posts_attributes # creates avatar_attributes= and posts_attributes= accepts_nested_attributes_for :avatar, :posts, :allow_destroy => true
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/dm-accepts_nested_attributes/nested_attributes.rb', line 39 def accepts_nested_attributes_for(association_name, = {}) assert_kind_of 'association_name', association_name, Symbol, String assert_kind_of 'options', , Hash = { :allow_destroy => false }.update() # raises if the specified option keys aren't valid () # raises if the specified association doesn't exist # we don't need the return value here, just the check # ------------------------------------------------------ # also, when using the return value from this call to # replace association_name with association.name, # has(1, :through) are broken, because they seem to have # a different name association_for_name(association_name) # should be safe to go on include InstanceMethods if ::DataMapper.const_defined?('Validate') require Pathname(__FILE__).dirname. + 'association_validation' include AssociationValidation end autosave_associations[association_name] = type = nr_of_possible_child_instances(association_name) > 1 ? :collection : :one_to_one class_eval %{ def save(context = :default) saved = false # preserve Resource#save api contract transaction { |t| t.rollback unless saved = super } saved end def #{association_name}_attributes @#{association_name}_attributes end def #{association_name}_attributes=(attributes) attributes = sanitize_nested_attributes(attributes) @#{association_name}_attributes = attributes assign_nested_attributes_for_#{type}_association(:#{association_name}, attributes, #{[:allow_destroy]}) end if association_type(:#{association_name}) == :many_to_one || association_type(:#{association_name}) == :one_to_one def get_#{association_name} #{association_name.to_s} || self.class.associated_model_for_name(:#{association_name}).new end end }, __FILE__, __LINE__ + 1 end |
#associated_model_for_name(association_name, repository = :default) ⇒ Object
i have the feeling this should be refactored
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/dm-accepts_nested_attributes/nested_attributes.rb', line 119 def associated_model_for_name(association_name, repository = :default) a = association_for_name(association_name, repository) case association_type(association_name) when :many_to_one a.parent_model when :one_to_one a.child_model when :one_to_many a.child_model when :many_to_many Object.full_const_get(a.[:child_model]) else raise ArgumentError, "Unknown association type #{a.inspect}" end end |
#association_for_name(name, repository = :default) ⇒ Object
avoid nil access by always going through this this method raises if the association named name is not established in this model
154 155 156 157 158 159 |
# File 'lib/dm-accepts_nested_attributes/nested_attributes.rb', line 154 def association_for_name(name, repository = :default) association = self.relationships(repository)[name] # TODO think about using a specific Error class like UnknownAssociationError raise(ArgumentError, "Relationship #{name.inspect} does not exist in \#{model}") unless association association end |
#association_type(association_name) ⇒ Object
maybe this should be provided by dm-core somehow DataMapper::Association::Relationship would be a place maybe?
137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
# File 'lib/dm-accepts_nested_attributes/nested_attributes.rb', line 137 def association_type(association_name) a = association_for_name(association_name) if a.[:max].nil? # belongs_to :many_to_one elsif a.[:max] == 1 # has(1) :one_to_one elsif a.[:max] > 1 && !a.is_a?(DataMapper::Associations::RelationshipChain) # has(n) :one_to_many elsif a.is_a?(DataMapper::Associations::RelationshipChain) # has(n, :through) MUST be checked after has(n) here :many_to_many else raise ArgumentError, "Unknown association type #{a.inspect}" end end |
#nr_of_possible_child_instances(association_name, repository = :default) ⇒ Object
utility methods
113 114 115 116 |
# File 'lib/dm-accepts_nested_attributes/nested_attributes.rb', line 113 def nr_of_possible_child_instances(association_name, repository = :default) # belongs_to seems to generate no options[:max] association_for_name(association_name, repository).[:max] || 1 end |
#reject_new_nested_attributes_proc_for(association_name) ⇒ Object
106 107 108 |
# File 'lib/dm-accepts_nested_attributes/nested_attributes.rb', line 106 def reject_new_nested_attributes_proc_for(association_name) autosave_associations[association_name] ? autosave_associations[association_name][:reject_if] : nil end |