activeentity 0.0.1.beta14 → 0.0.1.beta15
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/MIT-LICENSE +1 -1
- data/README.md +4 -4
- data/Rakefile +7 -7
- data/lib/active_entity.rb +29 -7
- data/lib/active_entity/aggregations.rb +2 -1
- data/lib/active_entity/associations.rb +46 -24
- data/lib/active_entity/associations/{embedded → embeds}/association.rb +2 -2
- data/lib/active_entity/associations/{embedded → embeds}/builder/association.rb +1 -1
- data/lib/active_entity/associations/{embedded → embeds}/builder/collection_association.rb +1 -1
- data/lib/active_entity/associations/{embedded → embeds}/builder/embedded_in.rb +1 -1
- data/lib/active_entity/associations/{embedded → embeds}/builder/embeds_many.rb +1 -1
- data/lib/active_entity/associations/{embedded → embeds}/builder/embeds_one.rb +1 -1
- data/lib/active_entity/associations/{embedded → embeds}/builder/singular_association.rb +1 -1
- data/lib/active_entity/associations/{embedded → embeds}/collection_association.rb +1 -1
- data/lib/active_entity/associations/{embedded → embeds}/collection_proxy.rb +2 -2
- data/lib/active_entity/associations/{embedded → embeds}/embedded_in_association.rb +1 -1
- data/lib/active_entity/associations/{embedded → embeds}/embeds_many_association.rb +1 -1
- data/lib/active_entity/associations/{embedded → embeds}/embeds_one_association.rb +2 -1
- data/lib/active_entity/associations/{embedded → embeds}/singular_association.rb +1 -1
- data/lib/active_entity/attribute_assignment.rb +9 -3
- data/lib/active_entity/attribute_methods.rb +12 -11
- data/lib/active_entity/attribute_methods/before_type_cast.rb +1 -1
- data/lib/active_entity/attribute_methods/dirty.rb +13 -0
- data/lib/active_entity/attribute_methods/primary_key.rb +1 -1
- data/lib/active_entity/attribute_methods/query.rb +11 -4
- data/lib/active_entity/attribute_methods/read.rb +1 -3
- data/lib/active_entity/attribute_methods/time_zone_conversion.rb +2 -0
- data/lib/active_entity/attribute_methods/write.rb +4 -6
- data/lib/active_entity/attributes.rb +76 -2
- data/lib/active_entity/base.rb +3 -12
- data/lib/active_entity/core.rb +97 -39
- data/lib/active_entity/define_callbacks.rb +4 -0
- data/lib/active_entity/enum.rb +30 -4
- data/lib/active_entity/errors.rb +0 -11
- data/lib/active_entity/gem_version.rb +1 -1
- data/lib/active_entity/inheritance.rb +4 -106
- data/lib/active_entity/integration.rb +1 -1
- data/lib/active_entity/model_schema.rb +0 -12
- data/lib/active_entity/nested_attributes.rb +5 -12
- data/lib/active_entity/railtie.rb +61 -1
- data/lib/active_entity/readonly_attributes.rb +9 -1
- data/lib/active_entity/reflection.rb +22 -19
- data/lib/active_entity/serialization.rb +9 -6
- data/lib/active_entity/store.rb +51 -2
- data/lib/active_entity/type.rb +8 -8
- data/lib/active_entity/type/registry.rb +5 -5
- data/lib/active_entity/{validate_embedded_association.rb → validate_embeds_association.rb} +6 -6
- data/lib/active_entity/validations.rb +2 -6
- data/lib/active_entity/validations/associated.rb +1 -1
- data/lib/active_entity/validations/{uniqueness_in_embedding.rb → uniqueness_in_embeds.rb} +1 -1
- data/lib/active_entity/validations/uniqueness_on_active_record.rb +46 -40
- metadata +27 -30
- data/lib/active_entity/type/decimal_without_scale.rb +0 -15
- data/lib/active_entity/type/hash_lookup_type_map.rb +0 -25
- data/lib/active_entity/type/type_map.rb +0 -62
- data/lib/tasks/active_entity_tasks.rake +0 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7f4a4f6e30f287b1ae750d510743b3cbb3c3ac40f00bcb56e9c5c634de23ce64
|
4
|
+
data.tar.gz: 91a3be9d2223600c26ff56e025ddd37ec3d520951cc033587d196599a8b10e72
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 924b81ffdd2d8835492f7566dc70d11486932ff913a3bea4569294545a9f3037b009e147e6bf77c222686a82596bda207620dd2cb07ec8334af9937ab03b7df6
|
7
|
+
data.tar.gz: da1b359c2ae9d9e0a1033bce6934c5fde0a18c96a78a8b63eaab4d5a83f71f75b241a59c5867cecaaff8033113d4c0bc0bdd094d04b3d0f057d113ad7a94c4b5
|
data/MIT-LICENSE
CHANGED
data/README.md
CHANGED
@@ -89,15 +89,15 @@ end
|
|
89
89
|
|
90
90
|
class Reviewer < ActiveEntity::Base
|
91
91
|
attribute :first_name, :string
|
92
|
-
attribute :last_name, :string
|
92
|
+
attribute :last_name, :string
|
93
93
|
end
|
94
94
|
|
95
95
|
class Book < ActiveEntity::Base
|
96
96
|
embeds_many :categories
|
97
|
-
validates :categories,
|
98
|
-
|
97
|
+
validates :categories, uniqueness_in_embeds: {key: :name}
|
98
|
+
|
99
99
|
embeds_many :reviewers
|
100
|
-
validates :categories,
|
100
|
+
validates :categories, uniqueness_in_embeds: {key: [:first_name, :last_name]}
|
101
101
|
end
|
102
102
|
```
|
103
103
|
|
data/Rakefile
CHANGED
@@ -1,21 +1,21 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
require "bundler/setup"
|
5
|
-
rescue LoadError
|
6
|
-
puts "You must `gem install bundler` and `bundle install` to run rake tasks"
|
7
|
-
end
|
8
|
-
|
3
|
+
require "bundler/setup"
|
9
4
|
require "rdoc/task"
|
10
5
|
|
11
6
|
RDoc::Task.new(:rdoc) do |rdoc|
|
12
7
|
rdoc.rdoc_dir = "rdoc"
|
13
|
-
rdoc.title = "
|
8
|
+
rdoc.title = "ActiveEntity"
|
14
9
|
rdoc.options << "--line-numbers"
|
15
10
|
rdoc.rdoc_files.include("README.md")
|
16
11
|
rdoc.rdoc_files.include("lib/**/*.rb")
|
17
12
|
end
|
18
13
|
|
14
|
+
APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__)
|
15
|
+
load "rails/tasks/engine.rake"
|
16
|
+
|
17
|
+
load "rails/tasks/statistics.rake"
|
18
|
+
|
19
19
|
require "bundler/gem_tasks"
|
20
20
|
|
21
21
|
require "rake/testtask"
|
data/lib/active_entity.rb
CHANGED
@@ -1,15 +1,38 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
#--
|
4
|
+
# Copyright (c) 2004-2020 David Heinemeier Hansson
|
5
|
+
#
|
6
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
7
|
+
# a copy of this software and associated documentation files (the
|
8
|
+
# "Software"), to deal in the Software without restriction, including
|
9
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
10
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
11
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
12
|
+
# the following conditions:
|
13
|
+
#
|
14
|
+
# The above copyright notice and this permission notice shall be
|
15
|
+
# included in all copies or substantial portions of the Software.
|
16
|
+
#
|
17
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
18
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
19
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
20
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
21
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
22
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
23
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
24
|
+
#++
|
25
|
+
|
3
26
|
require "active_support"
|
4
27
|
require "active_support/rails"
|
28
|
+
require "active_model"
|
5
29
|
require "yaml"
|
6
30
|
|
7
31
|
require "core_ext/array_without_blank"
|
8
32
|
|
9
|
-
require "active_model"
|
10
|
-
require "active_model/attribute_set"
|
11
|
-
|
12
33
|
require "active_entity/version"
|
34
|
+
require "active_model/attribute_set"
|
35
|
+
require "active_entity/errors"
|
13
36
|
|
14
37
|
module ActiveEntity
|
15
38
|
extend ActiveSupport::Autoload
|
@@ -30,13 +53,11 @@ module ActiveEntity
|
|
30
53
|
autoload :Validations
|
31
54
|
|
32
55
|
eager_autoload do
|
33
|
-
autoload :ActiveEntityError, "active_entity/errors"
|
34
|
-
|
35
56
|
autoload :Aggregations
|
36
57
|
autoload :Associations
|
37
58
|
autoload :AttributeAssignment
|
38
59
|
autoload :AttributeMethods
|
39
|
-
autoload :
|
60
|
+
autoload :ValidateEmbedsAssociation
|
40
61
|
|
41
62
|
autoload :Type
|
42
63
|
end
|
@@ -51,12 +72,13 @@ module ActiveEntity
|
|
51
72
|
|
52
73
|
eager_autoload do
|
53
74
|
autoload :BeforeTypeCast
|
75
|
+
autoload :Dirty
|
54
76
|
autoload :PrimaryKey
|
55
77
|
autoload :Query
|
56
|
-
autoload :Serialization
|
57
78
|
autoload :Read
|
58
79
|
autoload :TimeZoneConversion
|
59
80
|
autoload :Write
|
81
|
+
autoload :Serialization
|
60
82
|
end
|
61
83
|
end
|
62
84
|
|
@@ -133,7 +133,7 @@ module ActiveEntity
|
|
133
133
|
# converted to an instance of value class if necessary.
|
134
134
|
#
|
135
135
|
# For example, the +NetworkResource+ model has +network_address+ and +cidr_range+ attributes that should be
|
136
|
-
# aggregated using the +NetAddr::CIDR+ value class (
|
136
|
+
# aggregated using the +NetAddr::CIDR+ value class (https://www.rubydoc.info/gems/netaddr/1.5.0/NetAddr/CIDR).
|
137
137
|
# The constructor for the value class is called +create+ and it expects a CIDR address string as a parameter.
|
138
138
|
# New values can be assigned to the value object using either another +NetAddr::CIDR+ object, a string
|
139
139
|
# or an array. The <tt>:constructor</tt> and <tt>:converter</tt> options can be used to meet
|
@@ -234,6 +234,7 @@ module ActiveEntity
|
|
234
234
|
end
|
235
235
|
|
236
236
|
private
|
237
|
+
|
237
238
|
def reader_method(name, class_name, mapping, allow_nil, constructor)
|
238
239
|
define_method(name) do
|
239
240
|
if @aggregation_cache[name].nil? && (!allow_nil || mapping.any? { |key, _| !_read_attribute(key).nil? })
|
@@ -2,8 +2,6 @@
|
|
2
2
|
|
3
3
|
require "active_support/core_ext/enumerable"
|
4
4
|
require "active_support/core_ext/string/conversions"
|
5
|
-
require "active_support/core_ext/module/remove_method"
|
6
|
-
require "active_entity/errors"
|
7
5
|
|
8
6
|
module ActiveEntity
|
9
7
|
class AssociationNotFoundError < ConfigurationError #:nodoc:
|
@@ -30,25 +28,24 @@ module ActiveEntity
|
|
30
28
|
module Associations # :nodoc:
|
31
29
|
extend ActiveSupport::Autoload
|
32
30
|
extend ActiveSupport::Concern
|
33
|
-
|
34
31
|
# These classes will be loaded when associations are created.
|
35
32
|
# So there is no need to eager load them.
|
36
|
-
module
|
33
|
+
module Embeds
|
37
34
|
extend ActiveSupport::Autoload
|
38
35
|
|
39
|
-
autoload :Association, "active_entity/associations/
|
40
|
-
autoload :SingularAssociation, "active_entity/associations/
|
41
|
-
autoload :CollectionAssociation, "active_entity/associations/
|
42
|
-
autoload :CollectionProxy, "active_entity/associations/
|
36
|
+
autoload :Association, "active_entity/associations/embeds/association"
|
37
|
+
autoload :SingularAssociation, "active_entity/associations/embeds/singular_association"
|
38
|
+
autoload :CollectionAssociation, "active_entity/associations/embeds/collection_association"
|
39
|
+
autoload :CollectionProxy, "active_entity/associations/embeds/collection_proxy"
|
43
40
|
|
44
41
|
module Builder #:nodoc:
|
45
|
-
autoload :Association, "active_entity/associations/
|
46
|
-
autoload :SingularAssociation, "active_entity/associations/
|
47
|
-
autoload :CollectionAssociation, "active_entity/associations/
|
42
|
+
autoload :Association, "active_entity/associations/embeds/builder/association"
|
43
|
+
autoload :SingularAssociation, "active_entity/associations/embeds/builder/singular_association"
|
44
|
+
autoload :CollectionAssociation, "active_entity/associations/embeds/builder/collection_association"
|
48
45
|
|
49
|
-
autoload :EmbeddedIn, "active_entity/associations/
|
50
|
-
autoload :EmbedsOne, "active_entity/associations/
|
51
|
-
autoload :EmbedsMany, "active_entity/associations/
|
46
|
+
autoload :EmbeddedIn, "active_entity/associations/embeds/builder/embedded_in"
|
47
|
+
autoload :EmbedsOne, "active_entity/associations/embeds/builder/embeds_one"
|
48
|
+
autoload :EmbedsMany, "active_entity/associations/embeds/builder/embeds_many"
|
52
49
|
end
|
53
50
|
|
54
51
|
eager_autoload do
|
@@ -60,9 +57,8 @@ module ActiveEntity
|
|
60
57
|
|
61
58
|
def self.eager_load!
|
62
59
|
super
|
63
|
-
|
60
|
+
Embeds.eager_load!
|
64
61
|
end
|
65
|
-
|
66
62
|
# Returns the association instance for the given name, instantiating it if it doesn't already exist
|
67
63
|
def association(name) #:nodoc:
|
68
64
|
association = association_instance_get(name)
|
@@ -88,10 +84,6 @@ module ActiveEntity
|
|
88
84
|
end
|
89
85
|
|
90
86
|
private
|
91
|
-
# Clears out the association cache.
|
92
|
-
def clear_association_cache
|
93
|
-
@association_cache.clear if persisted?
|
94
|
-
end
|
95
87
|
|
96
88
|
def init_internals
|
97
89
|
@association_cache = {}
|
@@ -108,19 +100,49 @@ module ActiveEntity
|
|
108
100
|
@association_cache[name] = association
|
109
101
|
end
|
110
102
|
|
103
|
+
# \Associations are a set of macro-like class methods for tying objects together through
|
104
|
+
# foreign keys. They express relationships like "Project has one Project Manager"
|
105
|
+
# or "Project belongs to a Portfolio". Each macro adds a number of methods to the
|
106
|
+
# class which are specialized according to the collection or association symbol and the
|
107
|
+
# options hash. It works much the same way as Ruby's own <tt>attr*</tt>
|
108
|
+
# methods.
|
109
|
+
#
|
110
|
+
# class Project < ActiveEntity::Base
|
111
|
+
# belongs_to :portfolio
|
112
|
+
# has_one :project_manager
|
113
|
+
# has_many :milestones
|
114
|
+
# has_and_belongs_to_many :categories
|
115
|
+
# end
|
116
|
+
#
|
117
|
+
# The project class now has the following methods (and more) to ease the traversal and
|
118
|
+
# manipulation of its relationships:
|
119
|
+
# * <tt>Project#portfolio</tt>, <tt>Project#portfolio=(portfolio)</tt>, <tt>Project#reload_portfolio</tt>
|
120
|
+
# * <tt>Project#project_manager</tt>, <tt>Project#project_manager=(project_manager)</tt>, <tt>Project#reload_project_manager</tt>
|
121
|
+
# * <tt>Project#milestones.empty?</tt>, <tt>Project#milestones.size</tt>, <tt>Project#milestones</tt>, <tt>Project#milestones<<(milestone)</tt>,
|
122
|
+
# <tt>Project#milestones.delete(milestone)</tt>, <tt>Project#milestones.destroy(milestone)</tt>, <tt>Project#milestones.find(milestone_id)</tt>,
|
123
|
+
# <tt>Project#milestones.build</tt>, <tt>Project#milestones.create</tt>
|
124
|
+
# * <tt>Project#categories.empty?</tt>, <tt>Project#categories.size</tt>, <tt>Project#categories</tt>, <tt>Project#categories<<(category1)</tt>,
|
125
|
+
# <tt>Project#categories.delete(category1)</tt>, <tt>Project#categories.destroy(category1)</tt>
|
126
|
+
#
|
127
|
+
# === A word of warning
|
128
|
+
#
|
129
|
+
# Don't create associations that have the same name as {instance methods}[rdoc-ref:ActiveEntity::Core] of
|
130
|
+
# <tt>ActiveEntity::Base</tt>. Since the association adds a method with that name to
|
131
|
+
# its model, using an association with the same name as one provided by <tt>ActiveEntity::Base</tt> will override the method inherited through <tt>ActiveEntity::Base</tt> and will break things.
|
132
|
+
# For instance, +attributes+ and +connection+ would be bad choices for association names, because those names already exist in the list of <tt>ActiveEntity::Base</tt> instance methods.
|
111
133
|
module ClassMethods
|
112
134
|
def embedded_in(name, **options)
|
113
|
-
reflection =
|
135
|
+
reflection = Embeds::Builder::EmbeddedIn.build(self, name, options)
|
114
136
|
Reflection.add_reflection self, name, reflection
|
115
137
|
end
|
116
138
|
|
117
139
|
def embeds_one(name, **options)
|
118
|
-
reflection =
|
140
|
+
reflection = Embeds::Builder::EmbedsOne.build(self, name, options)
|
119
141
|
Reflection.add_reflection self, name, reflection
|
120
142
|
end
|
121
143
|
|
122
144
|
def embeds_many(name, **options)
|
123
|
-
reflection =
|
145
|
+
reflection = Embeds::Builder::EmbedsMany.build(self, name, options)
|
124
146
|
Reflection.add_reflection self, name, reflection
|
125
147
|
end
|
126
148
|
|
@@ -133,7 +155,7 @@ module ActiveEntity
|
|
133
155
|
end
|
134
156
|
end
|
135
157
|
|
136
|
-
def
|
158
|
+
def embeds_association_names
|
137
159
|
@association_names ||=
|
138
160
|
if !abstract_class?
|
139
161
|
reflections.select { |_, r| r.embedded? }.keys.map(&:to_sym)
|
@@ -4,7 +4,7 @@ require "active_support/core_ext/array/wrap"
|
|
4
4
|
|
5
5
|
module ActiveEntity
|
6
6
|
module Associations
|
7
|
-
module
|
7
|
+
module Embeds
|
8
8
|
# = Active Entity Associations
|
9
9
|
#
|
10
10
|
# This is the root class of all associations ('+ Foo' signifies an included module Foo):
|
@@ -83,7 +83,7 @@ module ActiveEntity
|
|
83
83
|
end
|
84
84
|
|
85
85
|
def initialize_attributes(record, attributes = {}) #:nodoc:
|
86
|
-
record.
|
86
|
+
record.assign_attributes attributes if attributes.any?
|
87
87
|
set_inverse_instance(record)
|
88
88
|
end
|
89
89
|
|
@@ -11,7 +11,7 @@
|
|
11
11
|
# - CollectionAssociation
|
12
12
|
# - HasManyAssociation
|
13
13
|
|
14
|
-
module ActiveEntity::Associations::
|
14
|
+
module ActiveEntity::Associations::Embeds::Builder # :nodoc:
|
15
15
|
class Association #:nodoc:
|
16
16
|
class << self
|
17
17
|
attr_accessor :extensions
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
require "active_entity/associations"
|
4
4
|
|
5
|
-
module ActiveEntity::Associations::
|
5
|
+
module ActiveEntity::Associations::Embeds::Builder # :nodoc:
|
6
6
|
class CollectionAssociation < Association #:nodoc:
|
7
7
|
CALLBACKS = [:before_add, :after_add, :before_remove, :after_remove]
|
8
8
|
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
# This class is inherited by the has_one and belongs_to association classes
|
4
4
|
|
5
|
-
module ActiveEntity::Associations::
|
5
|
+
module ActiveEntity::Associations::Embeds::Builder # :nodoc:
|
6
6
|
class SingularAssociation < Association #:nodoc:
|
7
7
|
def self.valid_options(options)
|
8
8
|
super + [:inverse_of, :required]
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module ActiveEntity
|
4
4
|
module Associations
|
5
|
-
module
|
5
|
+
module Embeds
|
6
6
|
# Association proxies in Active Entity are middlemen between the object that
|
7
7
|
# holds the association, known as the <tt>@owner</tt>, and the actual associated
|
8
8
|
# object, known as the <tt>@target</tt>. The kind of association any proxy is
|
@@ -40,7 +40,7 @@ module ActiveEntity
|
|
40
40
|
:[], :&, :|, :+, :-, :sample, :reverse, :rotate, :compact, :in_groups, :in_groups_of,
|
41
41
|
:find, :last, :take, :blank?, :present?, :empty?, :any?, :one?, :many?, :include?,
|
42
42
|
:to_sentence, :to_formatted_s, :as_json,
|
43
|
-
:shuffle, :split, :slice, :index, :rindex, to: :records
|
43
|
+
:shuffle, :split, :slice, :index, :rindex, :size, to: :records
|
44
44
|
|
45
45
|
def initialize(klass, association)
|
46
46
|
@klass = klass
|
@@ -2,10 +2,11 @@
|
|
2
2
|
|
3
3
|
module ActiveEntity
|
4
4
|
module Associations
|
5
|
-
module
|
5
|
+
module Embeds
|
6
6
|
# = Active Entity Has One Association
|
7
7
|
class EmbedsOneAssociation < SingularAssociation #:nodoc:
|
8
8
|
private
|
9
|
+
|
9
10
|
def replace(record)
|
10
11
|
self.target =
|
11
12
|
if record.is_a? reflection.klass
|
@@ -6,6 +6,10 @@ module ActiveEntity
|
|
6
6
|
module AttributeAssignment
|
7
7
|
include ActiveModel::AttributeAssignment
|
8
8
|
|
9
|
+
def assign_attributes(attributes)
|
10
|
+
super(attributes.dup)
|
11
|
+
end
|
12
|
+
|
9
13
|
private
|
10
14
|
|
11
15
|
def _assign_attributes(attributes)
|
@@ -13,10 +17,12 @@ module ActiveEntity
|
|
13
17
|
nested_parameter_attributes = {}
|
14
18
|
|
15
19
|
attributes.each do |k, v|
|
16
|
-
|
17
|
-
|
20
|
+
key = k.to_s
|
21
|
+
|
22
|
+
if key.include?("(")
|
23
|
+
multi_parameter_attributes[key] = attributes.delete(k)
|
18
24
|
elsif v.is_a?(Hash)
|
19
|
-
nested_parameter_attributes[
|
25
|
+
nested_parameter_attributes[key] = attributes.delete(k)
|
20
26
|
end
|
21
27
|
end
|
22
28
|
super(attributes)
|