active_data 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.rspec +1 -0
- data/.travis.yml +1 -1
- data/Gemfile +5 -7
- data/Guardfile +8 -3
- data/active_data.gemspec +2 -2
- data/lib/active_data/attributes/base.rb +10 -5
- data/lib/active_data/attributes/localized.rb +1 -1
- data/lib/active_data/model/associations/{many.rb → association.rb} +9 -3
- data/lib/active_data/model/associations/embeds_many.rb +33 -0
- data/lib/active_data/model/associations/embeds_one.rb +30 -0
- data/lib/active_data/model/associations.rb +19 -22
- data/lib/active_data/model/attributable.rb +35 -29
- data/lib/active_data/model/collectionizable.rb +13 -12
- data/lib/active_data/model/extensions/array.rb +3 -3
- data/lib/active_data/model/extensions/big_decimal.rb +2 -2
- data/lib/active_data/model/extensions/date.rb +1 -8
- data/lib/active_data/model/extensions/date_time.rb +17 -0
- data/lib/active_data/model/extensions/float.rb +1 -1
- data/lib/active_data/model/extensions/hash.rb +1 -1
- data/lib/active_data/model/extensions/integer.rb +1 -1
- data/lib/active_data/model/extensions/localized.rb +2 -2
- data/lib/active_data/model/extensions/object.rb +17 -0
- data/lib/active_data/model/extensions/time.rb +17 -0
- data/lib/active_data/model/localizable.rb +3 -3
- data/lib/active_data/model/nested_attributes.rb +10 -4
- data/lib/active_data/model.rb +17 -11
- data/lib/active_data/validations/associated.rb +17 -0
- data/lib/active_data/validations.rb +7 -0
- data/lib/active_data/version.rb +1 -1
- data/lib/active_data.rb +1 -1
- data/spec/lib/active_data/model/associations/embeds_many_spec.rb +93 -0
- data/spec/lib/active_data/model/associations/embeds_one_spec.rb +57 -0
- data/spec/lib/active_data/model/attributable_spec.rb +118 -2
- data/spec/lib/active_data/model/attributes/localized_spec.rb +1 -0
- data/spec/lib/active_data/model/collectionizable_spec.rb +41 -15
- data/spec/lib/active_data/model/nested_attributes_spec.rb +47 -26
- data/spec/lib/active_data/model/type_cast_spec.rb +31 -3
- data/spec/lib/active_data/model_spec.rb +26 -7
- data/spec/lib/active_data/validations/associated_spec.rb +88 -0
- metadata +27 -16
- data/spec/lib/active_data/model/associations_spec.rb +0 -35
data/.rspec
CHANGED
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
@@ -3,12 +3,10 @@ source 'https://rubygems.org'
|
|
3
3
|
# Specify your gem's dependencies in active_data.gemspec
|
4
4
|
gemspec
|
5
5
|
|
6
|
+
gem 'timecop'
|
7
|
+
|
6
8
|
gem 'guard'
|
7
9
|
gem 'guard-rspec'
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
else
|
12
|
-
gem 'rb-inotify'
|
13
|
-
gem 'libnotify'
|
14
|
-
end
|
10
|
+
gem 'rb-inotify', require: false
|
11
|
+
gem 'rb-fsevent', require: false
|
12
|
+
gem 'rb-fchange', require: false
|
data/Guardfile
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# A sample Guardfile
|
2
2
|
# More info at https://github.com/guard/guard#readme
|
3
3
|
|
4
|
-
guard
|
4
|
+
guard :rspec do
|
5
5
|
watch(%r{^spec/.+_spec\.rb$})
|
6
6
|
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
7
7
|
watch('spec/spec_helper.rb') { "spec" }
|
@@ -13,7 +13,12 @@ guard 'rspec', :version => 2 do
|
|
13
13
|
watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
|
14
14
|
watch('config/routes.rb') { "spec/routing" }
|
15
15
|
watch('app/controllers/application_controller.rb') { "spec/controllers" }
|
16
|
-
|
17
|
-
|
16
|
+
|
17
|
+
# Capybara features specs
|
18
|
+
watch(%r{^app/views/(.+)/.*\.(erb|haml)$}) { |m| "spec/features/#{m[1]}_spec.rb" }
|
19
|
+
|
20
|
+
# Turnip features and steps
|
21
|
+
watch(%r{^spec/acceptance/(.+)\.feature$})
|
22
|
+
watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
|
18
23
|
end
|
19
24
|
|
data/active_data.gemspec
CHANGED
@@ -17,6 +17,6 @@ Gem::Specification.new do |gem|
|
|
17
17
|
|
18
18
|
gem.add_development_dependency "rake"
|
19
19
|
gem.add_development_dependency "rspec"
|
20
|
-
gem.add_runtime_dependency "activesupport"
|
21
|
-
gem.add_runtime_dependency "activemodel"
|
20
|
+
gem.add_runtime_dependency "activesupport", "~> 3.0"
|
21
|
+
gem.add_runtime_dependency "activemodel", "~> 3.0"
|
22
22
|
end
|
@@ -10,7 +10,7 @@ module ActiveData
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def type
|
13
|
-
@type ||= options[:type] ||
|
13
|
+
@type ||= options[:type] || Object
|
14
14
|
end
|
15
15
|
|
16
16
|
def values
|
@@ -18,15 +18,20 @@ module ActiveData
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def default
|
21
|
-
@default ||= options[:default]
|
21
|
+
@default ||= @options[:default]
|
22
|
+
end
|
23
|
+
|
24
|
+
def default_blank?
|
25
|
+
@default_blank ||= !!@options[:default_blank]
|
22
26
|
end
|
23
27
|
|
24
28
|
def default_value instance
|
25
|
-
default.call instance
|
29
|
+
default.respond_to?(:call) ? default.call(instance) : default unless default.nil?
|
26
30
|
end
|
27
31
|
|
28
32
|
def type_cast value
|
29
|
-
|
33
|
+
return value if value.instance_of?(type)
|
34
|
+
type.active_data_type_cast(value)
|
30
35
|
end
|
31
36
|
|
32
37
|
def generate_instance_methods context
|
@@ -49,7 +54,7 @@ module ActiveData
|
|
49
54
|
EOS
|
50
55
|
end
|
51
56
|
|
52
|
-
def
|
57
|
+
def generate_class_methods context
|
53
58
|
if values
|
54
59
|
context.class_eval <<-EOS
|
55
60
|
def #{name}_values
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module ActiveData
|
2
2
|
module Model
|
3
3
|
module Associations
|
4
|
-
class
|
4
|
+
class Association
|
5
5
|
attr_reader :name, :klass, :options
|
6
6
|
|
7
7
|
def initialize name, options = {}
|
@@ -14,10 +14,16 @@ module ActiveData
|
|
14
14
|
klass.to_s
|
15
15
|
end
|
16
16
|
|
17
|
-
def
|
18
|
-
|
17
|
+
def define_accessor klass
|
18
|
+
define_reader klass
|
19
|
+
define_writer klass
|
19
20
|
end
|
20
21
|
|
22
|
+
def define_reader klass
|
23
|
+
end
|
24
|
+
|
25
|
+
def define_writer klass
|
26
|
+
end
|
21
27
|
end
|
22
28
|
end
|
23
29
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module ActiveData
|
2
|
+
module Model
|
3
|
+
module Associations
|
4
|
+
class EmbedsMany < Association
|
5
|
+
|
6
|
+
def collection?
|
7
|
+
true
|
8
|
+
end
|
9
|
+
|
10
|
+
def define_reader target
|
11
|
+
target.class_eval <<-EOS
|
12
|
+
def #{name}
|
13
|
+
@#{name} ||= begin
|
14
|
+
association = self.class.reflect_on_association('#{name}')
|
15
|
+
association.klass.collection
|
16
|
+
end
|
17
|
+
end
|
18
|
+
EOS
|
19
|
+
end
|
20
|
+
|
21
|
+
def define_writer target
|
22
|
+
target.class_eval <<-EOS
|
23
|
+
def #{name}= value
|
24
|
+
association = self.class.reflect_on_association('#{name}')
|
25
|
+
@#{name} = association.klass.collection(value)
|
26
|
+
end
|
27
|
+
EOS
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module ActiveData
|
2
|
+
module Model
|
3
|
+
module Associations
|
4
|
+
class EmbedsOne < Association
|
5
|
+
|
6
|
+
def collection?
|
7
|
+
false
|
8
|
+
end
|
9
|
+
|
10
|
+
def define_reader target
|
11
|
+
target.class_eval <<-EOS
|
12
|
+
def #{name}
|
13
|
+
@#{name}
|
14
|
+
end
|
15
|
+
EOS
|
16
|
+
end
|
17
|
+
|
18
|
+
def define_writer target
|
19
|
+
target.class_eval <<-EOS
|
20
|
+
def #{name}= value
|
21
|
+
association = self.class.reflect_on_association('#{name}')
|
22
|
+
@#{name} = association.klass.instantiate(value) if value
|
23
|
+
end
|
24
|
+
EOS
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -1,4 +1,6 @@
|
|
1
|
-
require 'active_data/model/associations/
|
1
|
+
require 'active_data/model/associations/association'
|
2
|
+
require 'active_data/model/associations/embeds_many'
|
3
|
+
require 'active_data/model/associations/embeds_one'
|
2
4
|
|
3
5
|
module ActiveData
|
4
6
|
module Model
|
@@ -6,14 +8,22 @@ module ActiveData
|
|
6
8
|
extend ActiveSupport::Concern
|
7
9
|
|
8
10
|
included do
|
9
|
-
class_attribute :_associations, :
|
10
|
-
self._associations =
|
11
|
+
class_attribute :_associations, instance_reader: false, instance_writer: false
|
12
|
+
self._associations = {}
|
13
|
+
|
14
|
+
{ embeds_many: EmbedsMany, embeds_one: EmbedsOne }.each do |(name, association_class)|
|
15
|
+
define_singleton_method name do |*args|
|
16
|
+
association = association_class.new *args
|
17
|
+
association.define_accessor self
|
18
|
+
self._associations = _associations.merge(association.name => association)
|
19
|
+
end
|
20
|
+
end
|
11
21
|
end
|
12
22
|
|
13
23
|
module ClassMethods
|
14
24
|
|
15
25
|
def reflect_on_association name
|
16
|
-
_associations[name]
|
26
|
+
_associations[name.to_s]
|
17
27
|
end
|
18
28
|
|
19
29
|
def associations
|
@@ -23,27 +33,14 @@ module ActiveData
|
|
23
33
|
def association_names
|
24
34
|
_associations.keys
|
25
35
|
end
|
36
|
+
end
|
26
37
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
define_collection_writer association
|
31
|
-
self._associations = _associations.merge!(association.name => association)
|
32
|
-
end
|
33
|
-
|
34
|
-
def define_collection_reader association
|
35
|
-
define_method association.name do
|
36
|
-
instance_variable_get("@#{association.name}") || association.klass.collection([])
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def define_collection_writer association
|
41
|
-
define_method "#{association.name}=" do |value|
|
42
|
-
instance_variable_set "@#{association.name}", association.klass.collection(value)
|
43
|
-
end
|
38
|
+
def == other
|
39
|
+
super(other) && self.class.association_names.all? do |association|
|
40
|
+
send(association) == other.send(association)
|
44
41
|
end
|
45
|
-
|
46
42
|
end
|
43
|
+
|
47
44
|
end
|
48
45
|
end
|
49
46
|
end
|
@@ -5,15 +5,21 @@ module ActiveData
|
|
5
5
|
|
6
6
|
included do
|
7
7
|
class_attribute :_attributes, :instance_reader => false, :instance_writer => false
|
8
|
-
self._attributes =
|
9
|
-
|
10
|
-
extend generated_class_attributes_methods
|
11
|
-
include generated_instance_attributes_methods
|
8
|
+
self._attributes = {}
|
12
9
|
|
13
10
|
delegate :attribute_default, :to => 'self.class'
|
14
11
|
end
|
15
12
|
|
16
13
|
module ClassMethods
|
14
|
+
def attribute name, options = {}, &block
|
15
|
+
attribute = build_attribute(name, options, &block)
|
16
|
+
self._attributes = _attributes.merge(attribute.name => attribute)
|
17
|
+
|
18
|
+
attribute.generate_instance_methods generated_instance_attributes_methods
|
19
|
+
attribute.generate_class_methods generated_class_attributes_methods
|
20
|
+
attribute
|
21
|
+
end
|
22
|
+
|
17
23
|
def build_attribute name, options = {}, &block
|
18
24
|
klass = case options[:type].to_s
|
19
25
|
when 'Localized'
|
@@ -24,47 +30,44 @@ module ActiveData
|
|
24
30
|
klass.new name, options, &block
|
25
31
|
end
|
26
32
|
|
27
|
-
def attribute name, options = {}, &block
|
28
|
-
attribute = build_attribute(name, options, &block)
|
29
|
-
self._attributes = _attributes.merge(attribute.name => attribute)
|
30
|
-
|
31
|
-
attribute.generate_instance_methods generated_instance_attributes_methods
|
32
|
-
attribute.generate_singleton_methods generated_class_attributes_methods
|
33
|
-
attribute
|
34
|
-
end
|
35
|
-
|
36
33
|
def generated_class_attributes_methods
|
37
|
-
@generated_class_attributes_methods ||= Module.new
|
34
|
+
@generated_class_attributes_methods ||= Module.new.tap { |proxy| extend proxy }
|
38
35
|
end
|
39
36
|
|
40
37
|
def generated_instance_attributes_methods
|
41
|
-
@generated_instance_attributes_methods ||= Module.new
|
38
|
+
@generated_instance_attributes_methods ||= Module.new.tap { |proxy| include proxy }
|
42
39
|
end
|
43
40
|
|
44
41
|
def initialize_attributes
|
45
|
-
_attributes.
|
46
|
-
result[name] = nil
|
47
|
-
result
|
48
|
-
end
|
42
|
+
Hash[_attributes.map { |(name, _)| [name, nil] }]
|
49
43
|
end
|
50
44
|
end
|
51
45
|
|
52
46
|
def read_attribute name
|
53
|
-
|
54
|
-
|
55
|
-
|
47
|
+
name = name.to_sym
|
48
|
+
if attributes_cache.key? name
|
49
|
+
attributes_cache[name]
|
50
|
+
else
|
51
|
+
attribute = self.class._attributes[name]
|
52
|
+
value = attribute.type_cast @attributes[name]
|
53
|
+
use_default = attribute.default_blank? && value.blank? || value.nil?
|
54
|
+
|
55
|
+
attributes_cache[name] = use_default ? attribute.default_value(self) : value
|
56
|
+
end
|
56
57
|
end
|
57
58
|
alias_method :[], :read_attribute
|
58
59
|
|
59
60
|
def has_attribute? name
|
60
|
-
@attributes.key? name
|
61
|
+
@attributes.key? name.to_sym
|
61
62
|
end
|
62
63
|
|
63
64
|
def read_attribute_before_type_cast name
|
64
|
-
@attributes[name]
|
65
|
+
@attributes[name.to_sym]
|
65
66
|
end
|
66
67
|
|
67
68
|
def write_attribute name, value
|
69
|
+
name = name.to_sym
|
70
|
+
attributes_cache.delete name
|
68
71
|
@attributes[name] = value
|
69
72
|
end
|
70
73
|
alias_method :[]=, :write_attribute
|
@@ -87,9 +90,10 @@ module ActiveData
|
|
87
90
|
def attributes= attributes
|
88
91
|
assign_attributes(attributes)
|
89
92
|
end
|
93
|
+
alias_method :update_attributes, :attributes=
|
90
94
|
|
91
|
-
def
|
92
|
-
|
95
|
+
def write_attributes attributes
|
96
|
+
attributes.each { |(name, value)| send("#{name}=", value) }
|
93
97
|
end
|
94
98
|
|
95
99
|
def reverse_update_attributes attributes
|
@@ -98,18 +102,20 @@ module ActiveData
|
|
98
102
|
|
99
103
|
private
|
100
104
|
|
105
|
+
def attributes_cache
|
106
|
+
@attributes_cache ||= {}
|
107
|
+
end
|
108
|
+
|
101
109
|
def assign_attributes attributes
|
102
110
|
(attributes.presence || {}).each do |(name, value)|
|
103
|
-
send("#{name}=", value) if respond_to?("#{name}=")
|
111
|
+
send("#{name}=", value) if has_attribute?(name) || respond_to?("#{name}=")
|
104
112
|
end
|
105
|
-
self.attributes
|
106
113
|
end
|
107
114
|
|
108
115
|
def reverse_assign_attributes attributes
|
109
116
|
(attributes.presence || {}).each do |(name, value)|
|
110
117
|
send("#{name}=", value) if respond_to?("#{name}=") && respond_to?(name) && send(name).blank?
|
111
118
|
end
|
112
|
-
self.attributes
|
113
119
|
end
|
114
120
|
|
115
121
|
end
|
@@ -6,27 +6,24 @@ module ActiveData
|
|
6
6
|
extend ActiveSupport::Concern
|
7
7
|
|
8
8
|
included do
|
9
|
-
|
9
|
+
class_attribute :_collection_superclass
|
10
|
+
collectionize
|
10
11
|
end
|
11
12
|
|
12
13
|
module ClassMethods
|
13
14
|
|
14
|
-
def collectionize collection_superclass =
|
15
|
-
|
16
|
-
include ActiveData::Model::Collectionizable::Proxy
|
17
|
-
end
|
18
|
-
collection.collectible = self
|
19
|
-
|
20
|
-
remove_const :Collection if const_defined? :Collection
|
21
|
-
const_set :Collection, collection
|
15
|
+
def collectionize collection_superclass = Array
|
16
|
+
self._collection_superclass = collection_superclass
|
22
17
|
end
|
23
18
|
|
24
|
-
def
|
19
|
+
def respond_to_missing? method, include_private
|
25
20
|
super || collection_class.superclass.method_defined?(method)
|
26
21
|
end
|
27
22
|
|
28
23
|
def method_missing method, *args, &block
|
29
|
-
|
24
|
+
collection_class.superclass.method_defined?(method) ?
|
25
|
+
current_scope.send(method, *args, &block) :
|
26
|
+
super
|
30
27
|
end
|
31
28
|
|
32
29
|
def collection source = nil
|
@@ -34,7 +31,11 @@ module ActiveData
|
|
34
31
|
end
|
35
32
|
|
36
33
|
def collection_class
|
37
|
-
@collection_class ||=
|
34
|
+
@collection_class ||= begin
|
35
|
+
Class.new(_collection_superclass) do
|
36
|
+
include ActiveData::Model::Collectionizable::Proxy
|
37
|
+
end.tap { |klass| klass.collectible = self }
|
38
|
+
end
|
38
39
|
end
|
39
40
|
|
40
41
|
def current_scope= value
|
@@ -7,10 +7,10 @@ module ActiveData
|
|
7
7
|
module ClassMethods
|
8
8
|
def active_data_type_cast value
|
9
9
|
case value
|
10
|
-
when
|
11
|
-
value.split(',').map(&:strip)
|
12
|
-
when Array then
|
10
|
+
when ::Array then
|
13
11
|
value
|
12
|
+
when ::String then
|
13
|
+
value.split(',').map(&:strip)
|
14
14
|
else
|
15
15
|
nil
|
16
16
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
module ActiveData
|
1
|
+
module ActiveData
|
2
2
|
module Model
|
3
3
|
module Extensions
|
4
4
|
module BigDecimal
|
@@ -6,7 +6,7 @@ module ActiveData
|
|
6
6
|
|
7
7
|
module ClassMethods
|
8
8
|
def active_data_type_cast value
|
9
|
-
::BigDecimal.new value.to_s if value
|
9
|
+
::BigDecimal.new Float(value).to_s rescue nil if value
|
10
10
|
end
|
11
11
|
end
|
12
12
|
end
|
@@ -6,14 +6,7 @@ module ActiveData
|
|
6
6
|
|
7
7
|
module ClassMethods
|
8
8
|
def active_data_type_cast value
|
9
|
-
|
10
|
-
when String then
|
11
|
-
Date.parse(value.to_s) rescue nil
|
12
|
-
when Date, DateTime, Time then
|
13
|
-
value.to_date
|
14
|
-
else
|
15
|
-
nil
|
16
|
-
end
|
9
|
+
value.to_date rescue nil
|
17
10
|
end
|
18
11
|
end
|
19
12
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module ActiveData
|
2
|
+
module Model
|
3
|
+
module Extensions
|
4
|
+
module DateTime
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
def active_data_type_cast value
|
9
|
+
value.to_datetime rescue nil
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
DateTime.send :include, ActiveData::Model::Extensions::DateTime
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module ActiveData
|
2
|
+
module Model
|
3
|
+
module Extensions
|
4
|
+
module Object
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
def active_data_type_cast value
|
9
|
+
value
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
Object.send :include, ActiveData::Model::Extensions::Object
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module ActiveData
|
2
|
+
module Model
|
3
|
+
module Extensions
|
4
|
+
module Time
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
def active_data_type_cast value
|
9
|
+
value.to_time rescue nil
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
Time.send :include, ActiveData::Model::Extensions::Time
|
@@ -17,13 +17,13 @@ module ActiveData
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def read_localized_attribute name, locale = self.class.locale
|
20
|
-
translations = read_attribute(name)
|
21
|
-
translations[self.class.fallbacks(locale).detect { |fallback| translations[fallback.to_s] }]
|
20
|
+
translations = read_attribute(name.to_s)
|
21
|
+
translations[self.class.fallbacks(locale).detect { |fallback| translations[fallback.to_s] }.to_s]
|
22
22
|
end
|
23
23
|
alias_method :read_localized_attribute_before_type_cast, :read_localized_attribute
|
24
24
|
|
25
25
|
def write_localized_attribute name, value, locale = self.class.locale
|
26
|
-
translations = read_attribute(name)
|
26
|
+
translations = read_attribute(name.to_s)
|
27
27
|
write_attribute(name, translations.merge(locale.to_s => value))
|
28
28
|
end
|
29
29
|
end
|
@@ -43,10 +43,16 @@ module ActiveData
|
|
43
43
|
|
44
44
|
reflection = self.class.reflect_on_association association_name
|
45
45
|
|
46
|
-
send
|
47
|
-
|
48
|
-
|
46
|
+
send "#{association_name}=", attributes_collection
|
47
|
+
end
|
48
|
+
|
49
|
+
def assign_nested_attributes_for_one_to_one_association(association_name, attributes, assignment_opts = {})
|
50
|
+
unless attributes.is_a?(Hash)
|
51
|
+
raise ArgumentError, "Hash expected, got #{attributes.class.name} (#{attributes.inspect})"
|
52
|
+
end
|
53
|
+
|
54
|
+
send "#{association_name}=", attributes
|
49
55
|
end
|
50
56
|
end
|
51
57
|
end
|
52
|
-
end
|
58
|
+
end
|