active_data 0.3.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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