active_data 0.3.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (142) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -1
  3. data/.rspec +0 -1
  4. data/.rvmrc +1 -1
  5. data/.travis.yml +13 -6
  6. data/Appraisals +7 -0
  7. data/Gemfile +1 -5
  8. data/Guardfile +68 -15
  9. data/README.md +144 -2
  10. data/active_data.gemspec +19 -11
  11. data/gemfiles/rails.4.0.gemfile +14 -0
  12. data/gemfiles/rails.4.1.gemfile +14 -0
  13. data/gemfiles/rails.4.2.gemfile +14 -0
  14. data/gemfiles/rails.5.0.gemfile +14 -0
  15. data/lib/active_data.rb +120 -3
  16. data/lib/active_data/active_record/associations.rb +50 -0
  17. data/lib/active_data/active_record/nested_attributes.rb +24 -0
  18. data/lib/active_data/config.rb +40 -0
  19. data/lib/active_data/errors.rb +93 -0
  20. data/lib/active_data/extensions.rb +33 -0
  21. data/lib/active_data/model.rb +16 -74
  22. data/lib/active_data/model/associations.rb +84 -15
  23. data/lib/active_data/model/associations/base.rb +79 -0
  24. data/lib/active_data/model/associations/collection/embedded.rb +12 -0
  25. data/lib/active_data/model/associations/collection/proxy.rb +32 -0
  26. data/lib/active_data/model/associations/collection/referenced.rb +26 -0
  27. data/lib/active_data/model/associations/embeds_many.rb +124 -18
  28. data/lib/active_data/model/associations/embeds_one.rb +90 -15
  29. data/lib/active_data/model/associations/nested_attributes.rb +180 -0
  30. data/lib/active_data/model/associations/references_many.rb +96 -0
  31. data/lib/active_data/model/associations/references_one.rb +83 -0
  32. data/lib/active_data/model/associations/reflections/base.rb +100 -0
  33. data/lib/active_data/model/associations/reflections/embeds_many.rb +25 -0
  34. data/lib/active_data/model/associations/reflections/embeds_one.rb +49 -0
  35. data/lib/active_data/model/associations/reflections/reference_reflection.rb +45 -0
  36. data/lib/active_data/model/associations/reflections/references_many.rb +28 -0
  37. data/lib/active_data/model/associations/reflections/references_one.rb +28 -0
  38. data/lib/active_data/model/associations/validations.rb +63 -0
  39. data/lib/active_data/model/attributes.rb +247 -0
  40. data/lib/active_data/model/attributes/attribute.rb +73 -0
  41. data/lib/active_data/model/attributes/base.rb +116 -0
  42. data/lib/active_data/model/attributes/collection.rb +17 -0
  43. data/lib/active_data/model/attributes/dictionary.rb +26 -0
  44. data/lib/active_data/model/attributes/localized.rb +42 -0
  45. data/lib/active_data/model/attributes/reference_many.rb +21 -0
  46. data/lib/active_data/model/attributes/reference_one.rb +42 -0
  47. data/lib/active_data/model/attributes/reflections/attribute.rb +55 -0
  48. data/lib/active_data/model/attributes/reflections/base.rb +62 -0
  49. data/lib/active_data/model/attributes/reflections/collection.rb +10 -0
  50. data/lib/active_data/model/attributes/reflections/dictionary.rb +13 -0
  51. data/lib/active_data/model/attributes/reflections/localized.rb +43 -0
  52. data/lib/active_data/model/attributes/reflections/reference_many.rb +10 -0
  53. data/lib/active_data/model/attributes/reflections/reference_one.rb +58 -0
  54. data/lib/active_data/model/attributes/reflections/represents.rb +55 -0
  55. data/lib/active_data/model/attributes/represents.rb +64 -0
  56. data/lib/active_data/model/callbacks.rb +71 -0
  57. data/lib/active_data/model/conventions.rb +35 -0
  58. data/lib/active_data/model/dirty.rb +77 -0
  59. data/lib/active_data/model/lifecycle.rb +307 -0
  60. data/lib/active_data/model/localization.rb +21 -0
  61. data/lib/active_data/model/persistence.rb +57 -0
  62. data/lib/active_data/model/primary.rb +51 -0
  63. data/lib/active_data/model/scopes.rb +77 -0
  64. data/lib/active_data/model/validations.rb +27 -0
  65. data/lib/active_data/model/validations/associated.rb +19 -0
  66. data/lib/active_data/model/validations/nested.rb +39 -0
  67. data/lib/active_data/railtie.rb +7 -0
  68. data/lib/active_data/version.rb +1 -1
  69. data/spec/lib/active_data/active_record/associations_spec.rb +149 -0
  70. data/spec/lib/active_data/active_record/nested_attributes_spec.rb +16 -0
  71. data/spec/lib/active_data/config_spec.rb +44 -0
  72. data/spec/lib/active_data/model/associations/embeds_many_spec.rb +362 -52
  73. data/spec/lib/active_data/model/associations/embeds_one_spec.rb +250 -31
  74. data/spec/lib/active_data/model/associations/nested_attributes_spec.rb +23 -0
  75. data/spec/lib/active_data/model/associations/references_many_spec.rb +196 -0
  76. data/spec/lib/active_data/model/associations/references_one_spec.rb +134 -0
  77. data/spec/lib/active_data/model/associations/reflections/embeds_many_spec.rb +144 -0
  78. data/spec/lib/active_data/model/associations/reflections/embeds_one_spec.rb +116 -0
  79. data/spec/lib/active_data/model/associations/reflections/references_many_spec.rb +255 -0
  80. data/spec/lib/active_data/model/associations/reflections/references_one_spec.rb +208 -0
  81. data/spec/lib/active_data/model/associations/validations_spec.rb +153 -0
  82. data/spec/lib/active_data/model/associations_spec.rb +189 -0
  83. data/spec/lib/active_data/model/attributes/attribute_spec.rb +144 -0
  84. data/spec/lib/active_data/model/attributes/base_spec.rb +82 -0
  85. data/spec/lib/active_data/model/attributes/collection_spec.rb +73 -0
  86. data/spec/lib/active_data/model/attributes/dictionary_spec.rb +93 -0
  87. data/spec/lib/active_data/model/attributes/localized_spec.rb +88 -33
  88. data/spec/lib/active_data/model/attributes/reflections/attribute_spec.rb +72 -0
  89. data/spec/lib/active_data/model/attributes/reflections/base_spec.rb +56 -0
  90. data/spec/lib/active_data/model/attributes/reflections/collection_spec.rb +37 -0
  91. data/spec/lib/active_data/model/attributes/reflections/dictionary_spec.rb +43 -0
  92. data/spec/lib/active_data/model/attributes/reflections/localized_spec.rb +37 -0
  93. data/spec/lib/active_data/model/attributes/reflections/represents_spec.rb +70 -0
  94. data/spec/lib/active_data/model/attributes/represents_spec.rb +153 -0
  95. data/spec/lib/active_data/model/attributes_spec.rb +243 -0
  96. data/spec/lib/active_data/model/callbacks_spec.rb +338 -0
  97. data/spec/lib/active_data/model/conventions_spec.rb +12 -0
  98. data/spec/lib/active_data/model/dirty_spec.rb +75 -0
  99. data/spec/lib/active_data/model/lifecycle_spec.rb +330 -0
  100. data/spec/lib/active_data/model/nested_attributes.rb +202 -0
  101. data/spec/lib/active_data/model/persistence_spec.rb +47 -0
  102. data/spec/lib/active_data/model/primary_spec.rb +84 -0
  103. data/spec/lib/active_data/model/scopes_spec.rb +88 -0
  104. data/spec/lib/active_data/model/typecasting_spec.rb +192 -0
  105. data/spec/lib/active_data/model/validations/associated_spec.rb +94 -0
  106. data/spec/lib/active_data/model/validations/nested_spec.rb +93 -0
  107. data/spec/lib/active_data/model/validations_spec.rb +31 -0
  108. data/spec/lib/active_data/model_spec.rb +1 -32
  109. data/spec/lib/active_data_spec.rb +12 -0
  110. data/spec/spec_helper.rb +39 -0
  111. data/spec/support/model_helpers.rb +10 -0
  112. metadata +246 -54
  113. data/gemfiles/Gemfile.rails-3 +0 -14
  114. data/lib/active_data/attributes/base.rb +0 -69
  115. data/lib/active_data/attributes/localized.rb +0 -42
  116. data/lib/active_data/model/associations/association.rb +0 -30
  117. data/lib/active_data/model/attributable.rb +0 -122
  118. data/lib/active_data/model/collectionizable.rb +0 -55
  119. data/lib/active_data/model/collectionizable/proxy.rb +0 -42
  120. data/lib/active_data/model/extensions.rb +0 -9
  121. data/lib/active_data/model/extensions/array.rb +0 -24
  122. data/lib/active_data/model/extensions/big_decimal.rb +0 -17
  123. data/lib/active_data/model/extensions/boolean.rb +0 -38
  124. data/lib/active_data/model/extensions/date.rb +0 -17
  125. data/lib/active_data/model/extensions/date_time.rb +0 -17
  126. data/lib/active_data/model/extensions/float.rb +0 -17
  127. data/lib/active_data/model/extensions/hash.rb +0 -22
  128. data/lib/active_data/model/extensions/integer.rb +0 -17
  129. data/lib/active_data/model/extensions/localized.rb +0 -22
  130. data/lib/active_data/model/extensions/object.rb +0 -17
  131. data/lib/active_data/model/extensions/string.rb +0 -17
  132. data/lib/active_data/model/extensions/time.rb +0 -17
  133. data/lib/active_data/model/localizable.rb +0 -31
  134. data/lib/active_data/model/nested_attributes.rb +0 -58
  135. data/lib/active_data/model/parameterizable.rb +0 -29
  136. data/lib/active_data/validations.rb +0 -7
  137. data/lib/active_data/validations/associated.rb +0 -17
  138. data/spec/lib/active_data/model/attributable_spec.rb +0 -191
  139. data/spec/lib/active_data/model/collectionizable_spec.rb +0 -60
  140. data/spec/lib/active_data/model/nested_attributes_spec.rb +0 -67
  141. data/spec/lib/active_data/model/type_cast_spec.rb +0 -116
  142. data/spec/lib/active_data/validations/associated_spec.rb +0 -88
@@ -1,60 +0,0 @@
1
- # encoding: UTF-8
2
- require 'spec_helper'
3
-
4
- describe ActiveData::Model::Collectionizable do
5
- let(:klass) do
6
- Class.new do
7
- include ActiveData::Model
8
-
9
- attribute :name
10
-
11
- def self.except_first
12
- self[1..-1]
13
- end
14
-
15
- def self.no_mars
16
- delete_if { |i| i.name == 'Mars' }
17
- end
18
- end
19
- end
20
-
21
- class CollectionizableTest
22
- include ActiveData::Model
23
- end
24
-
25
- let(:collection) { klass.collection([{ name: 'Hello' }, { name: 'World' }, { name: 'Mars' }]) }
26
-
27
- specify { klass.collection_class.should_not be_nil }
28
- specify { klass.collection_class.collectible.should == klass }
29
- specify { klass.collection_class.new.should be_empty }
30
- specify { CollectionizableTest.collection_class.should < Array }
31
-
32
- specify { collection.should be_instance_of klass.collection_class }
33
- specify { collection.except_first.should be_instance_of klass.collection_class }
34
- specify { collection.no_mars.should be_instance_of klass.collection_class }
35
- specify { collection.except_first.should == klass.collection([{ name: 'World' }, { name: 'Mars' }]) }
36
- specify { collection.no_mars.should == klass.collection([{ name: 'Hello' }, { name: 'World' }]) }
37
- specify { collection.except_first.no_mars.should == klass.collection([{ name: 'World' }]) }
38
- specify { collection.no_mars.except_first.should == klass.collection([{ name: 'World' }]) }
39
-
40
- context do
41
- let!(:ancestor) do
42
- Class.new do
43
- include ActiveData::Model
44
- end
45
- end
46
-
47
- let!(:descendant1) do
48
- Class.new ancestor
49
- end
50
-
51
- let!(:descendant2) do
52
- Class.new ancestor
53
- end
54
-
55
- specify { descendant1.collection_class.should < Array }
56
- specify { descendant2.collection_class.should < Array }
57
- specify { ancestor.collection_class.should_not == descendant1.collection_class }
58
- specify { descendant1.collection_class.should_not == descendant2.collection_class }
59
- end
60
- end
@@ -1,67 +0,0 @@
1
- # encoding: UTF-8
2
- require 'spec_helper'
3
-
4
- describe ActiveData::Model::Associations do
5
-
6
- class NestedAssoc
7
- include ActiveData::Model
8
-
9
- attribute :name
10
- end
11
-
12
- context do
13
- let(:klass) do
14
- Class.new do
15
- include ActiveData::Model
16
-
17
- attribute :name
18
- embeds_one :assoc, class_name: NestedAssoc
19
-
20
- accepts_nested_attributes_for :assoc
21
- end
22
- end
23
- let(:instance) { klass.new( name: 'world') }
24
-
25
- context do
26
- before { instance.assoc_attributes = { name: 'foo'} }
27
- specify { instance.assoc.should be_instance_of NestedAssoc }
28
- specify { instance.assoc.name.should == 'foo' }
29
- end
30
- end
31
-
32
- context do
33
- let(:klass) do
34
- Class.new do
35
- include ActiveData::Model
36
-
37
- attribute :name
38
- embeds_many :assocs, class_name: NestedAssoc
39
-
40
- accepts_nested_attributes_for :assocs
41
- end
42
- end
43
- let(:instance) { klass.new(name: 'world') }
44
-
45
- context do
46
- before { instance.assocs_attributes = [{ name: 'foo' }, { name: 'bar' }] }
47
- specify { instance.assocs.count.should == 2 }
48
- specify { instance.assocs.first.name.should == 'foo' }
49
- specify { instance.assocs.last.name.should == 'bar' }
50
- end
51
-
52
- context do
53
- before { instance.assocs_attributes = {1 => { name: 'baz' }, 2 => { name: 'foo' }} }
54
- specify { instance.assocs.count.should == 2 }
55
- specify { instance.assocs.first.name.should == 'baz' }
56
- specify { instance.assocs.last.name.should == 'foo' }
57
- end
58
-
59
- context do
60
- before { instance.assocs_attributes = {1 => { name: 'baz' }, 2 => { name: 'foo' }} }
61
- specify { instance.to_params.should == {
62
- "name" => "world",
63
- "assocs_attributes" => {'0' => {"name" => "baz"}, '1' => {"name" => "foo"}}
64
- } }
65
- end
66
- end
67
- end
@@ -1,116 +0,0 @@
1
- # encoding: UTF-8
2
- require 'spec_helper'
3
-
4
- describe 'typecasting' do
5
- let(:klass) do
6
- Class.new do
7
- include ActiveData::Model::Attributable
8
- attr_reader :name
9
-
10
- attribute :string, type: String
11
- attribute :integer, type: Integer
12
- attribute :float, type: Float
13
- attribute :big_decimal, type: BigDecimal
14
- attribute :boolean, type: Boolean
15
- attribute :array, type: Array
16
- attribute :date, type: Date
17
- attribute :datetime, type: DateTime
18
- attribute :time, type: Time
19
-
20
- def initialize name = nil
21
- @attributes = self.class.initialize_attributes
22
- @name = name
23
- end
24
- end
25
- end
26
-
27
- subject{klass.new}
28
-
29
- context 'string' do
30
- specify{subject.tap{|s| s.string = 'hello'}.string.should == 'hello'}
31
- specify{subject.tap{|s| s.string = 123}.string.should == '123'}
32
- specify{subject.tap{|s| s.string = nil}.string.should == nil}
33
- end
34
-
35
- context 'integer' do
36
- specify{subject.tap{|s| s.integer = 'hello'}.integer.should == nil}
37
- specify{subject.tap{|s| s.integer = '123hello'}.integer.should == nil}
38
- specify{subject.tap{|s| s.integer = '123'}.integer.should == 123}
39
- specify{subject.tap{|s| s.integer = '123.5'}.integer.should == 123}
40
- specify{subject.tap{|s| s.integer = 123}.integer.should == 123}
41
- specify{subject.tap{|s| s.integer = 123.5}.integer.should == 123}
42
- specify{subject.tap{|s| s.integer = nil}.integer.should == nil}
43
- specify{subject.tap{|s| s.integer = [123]}.integer.should == nil}
44
- end
45
-
46
- context 'float' do
47
- specify{subject.tap{|s| s.float = 'hello'}.float.should == nil}
48
- specify{subject.tap{|s| s.float = '123hello'}.float.should == nil}
49
- specify{subject.tap{|s| s.float = '123'}.float.should == 123.0}
50
- specify{subject.tap{|s| s.float = '123.'}.float.should == nil}
51
- specify{subject.tap{|s| s.float = '123.5'}.float.should == 123.5}
52
- specify{subject.tap{|s| s.float = 123}.float.should == 123.0}
53
- specify{subject.tap{|s| s.float = 123.5}.float.should == 123.5}
54
- specify{subject.tap{|s| s.float = nil}.float.should == nil}
55
- specify{subject.tap{|s| s.float = [123.5]}.float.should == nil}
56
- end
57
-
58
- context 'big_decimal' do
59
- specify{subject.tap{|s| s.big_decimal = 'hello'}.big_decimal.should == nil}
60
- specify{subject.tap{|s| s.big_decimal = '123hello'}.big_decimal.should == nil}
61
- specify{subject.tap{|s| s.big_decimal = '123'}.big_decimal.should == BigDecimal.new('123.0')}
62
- specify{subject.tap{|s| s.big_decimal = '123.'}.big_decimal.should == nil}
63
- specify{subject.tap{|s| s.big_decimal = '123.5'}.big_decimal.should == BigDecimal.new('123.5')}
64
- specify{subject.tap{|s| s.big_decimal = 123}.big_decimal.should == BigDecimal.new('123.0')}
65
- specify{subject.tap{|s| s.big_decimal = 123.5}.big_decimal.should == BigDecimal.new('123.5')}
66
- specify{subject.tap{|s| s.big_decimal = nil}.big_decimal.should == nil}
67
- specify{subject.tap{|s| s.big_decimal = [123.5]}.big_decimal.should == nil}
68
- end
69
-
70
- context 'boolean' do
71
- specify{subject.tap{|s| s.boolean = 'hello'}.boolean.should == nil}
72
- specify{subject.tap{|s| s.boolean = 'true'}.boolean.should == true}
73
- specify{subject.tap{|s| s.boolean = 'false'}.boolean.should == false}
74
- specify{subject.tap{|s| s.boolean = '1'}.boolean.should == true}
75
- specify{subject.tap{|s| s.boolean = '0'}.boolean.should == false}
76
- specify{subject.tap{|s| s.boolean = true}.boolean.should == true}
77
- specify{subject.tap{|s| s.boolean = false}.boolean.should == false}
78
- specify{subject.tap{|s| s.boolean = 1}.boolean.should == true}
79
- specify{subject.tap{|s| s.boolean = 0}.boolean.should == false}
80
- specify{subject.tap{|s| s.boolean = nil}.boolean.should == nil}
81
- specify{subject.tap{|s| s.boolean = [123]}.boolean.should == nil}
82
- end
83
-
84
- context 'array' do
85
- specify{subject.tap{|s| s.array = [1, 2, 3]}.array.should == [1, 2, 3]}
86
- specify{subject.tap{|s| s.array = 'hello, world'}.array.should == ['hello', 'world']}
87
- specify{subject.tap{|s| s.array = 10}.array.should == nil}
88
- end
89
-
90
- context 'date' do
91
- let(:date) { Date.new(2013, 6, 13) }
92
- specify{subject.tap{|s| s.date = nil}.date.should == nil}
93
- specify{subject.tap{|s| s.date = '2013-06-13'}.date.should == date}
94
- specify{subject.tap{|s| s.date = '2013-55-55'}.date.should == nil}
95
- specify{subject.tap{|s| s.date = DateTime.new(2013, 6, 13, 23, 13)}.date.should == date}
96
- specify{subject.tap{|s| s.date = Time.new(2013, 6, 13, 23, 13)}.date.should == date}
97
- end
98
-
99
- context 'datetime' do
100
- let(:datetime) { DateTime.new(2013, 6, 13, 23, 13) }
101
- specify{subject.tap{|s| s.datetime = nil}.datetime.should == nil}
102
- specify{subject.tap{|s| s.datetime = '2013-06-13 23:13'}.datetime.should == datetime}
103
- specify{subject.tap{|s| s.datetime = '2013-55-55 55:55'}.datetime.should == nil}
104
- specify{subject.tap{|s| s.datetime = Date.new(2013, 6, 13)}.datetime.should == DateTime.new(2013, 6, 13, 0, 0)}
105
- specify{subject.tap{|s| s.datetime = Time.utc(2013, 6, 13, 23, 13).utc}.datetime.should == DateTime.new(2013, 6, 13, 23, 13)}
106
- end
107
-
108
- context 'time' do
109
- let(:time) { Time.utc(2013, 6, 13, 23, 13) }
110
- specify{subject.tap{|s| s.time = nil}.time.should == nil}
111
- # specify{subject.tap{|s| s.time = '2013-06-13 23:13'}.time.should == time}
112
- specify{subject.tap{|s| s.time = '2013-55-55 55:55'}.time.should == nil}
113
- specify{subject.tap{|s| s.time = Date.new(2013, 6, 13)}.time.should == Time.new(2013, 6, 13, 0, 0)}
114
- specify{subject.tap{|s| s.time = DateTime.new(2013, 6, 13, 23, 13)}.time.should == time}
115
- end
116
- end
@@ -1,88 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe ActiveData::Validations do
4
- let(:main) do
5
- Class.new do
6
- def self.model_name
7
- ActiveModel::Name.new(self, nil, "Main")
8
- end
9
-
10
- include ActiveData::Model
11
- include ActiveData::Validations
12
-
13
- attribute :name
14
-
15
- validates_presence_of :name
16
- validates_associated :validated_one, :unvalidated_one, :validated_many, :unvalidated_many
17
-
18
- embeds_one :validated_one, class_name: ValidatedAssoc
19
- embeds_one :unvalidated_one, class_name: UnvalidatedAssoc
20
- embeds_many :validated_many, class_name: ValidatedAssoc
21
- embeds_many :unvalidated_many, class_name: UnvalidatedAssoc
22
- end
23
- end
24
-
25
- class ValidatedAssoc
26
- include ActiveData::Model
27
-
28
- attribute :name
29
-
30
- validates_presence_of :name
31
- end
32
-
33
- class UnvalidatedAssoc
34
- include ActiveData::Model
35
-
36
- attribute :name
37
- end
38
-
39
- context do
40
- subject(:instance) { main.new name: 'hello', validated_one: { name: 'name' } }
41
- it { should be_valid }
42
- end
43
-
44
- context do
45
- subject(:instance) { main.new name: 'hello', validated_one: { } }
46
- it { should_not be_valid }
47
- end
48
-
49
- context do
50
- subject(:instance) { main.new name: 'hello', unvalidated_one: { name: 'name' } }
51
- it { should be_valid }
52
- end
53
-
54
- context do
55
- subject(:instance) { main.new name: 'hello', unvalidated_one: { } }
56
- it { should be_valid }
57
- end
58
-
59
- context do
60
- subject(:instance) { main.new name: 'hello', validated_many: [{ name: 'name' }] }
61
- it { should be_valid }
62
- end
63
-
64
- context do
65
- subject(:instance) { main.new name: 'hello', validated_many: [{ }] }
66
- it { should_not be_valid }
67
- end
68
-
69
- context do
70
- subject(:instance) { main.new name: 'hello', unvalidated_many: [{ name: 'name' }] }
71
- it { should be_valid }
72
- end
73
-
74
- context do
75
- subject(:instance) { main.new name: 'hello', unvalidated_many: [{ }] }
76
- it { should be_valid }
77
- end
78
-
79
- context do
80
- subject(:instance) { main.new name: 'hello', validated_many: [{ name: 'name' }], validated_one: { } }
81
- it { should_not be_valid }
82
- end
83
-
84
- context do
85
- subject(:instance) { main.new name: 'hello', validated_many: [{ }], validated_one: { name: 'name' } }
86
- it { should_not be_valid }
87
- end
88
- end