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,14 +0,0 @@
1
- source "http://rubygems.org"
2
-
3
- gemspec path: '../'
4
-
5
- gem 'activesupport', '~> 3.0'
6
- gem 'activemodel', '~> 3.0'
7
-
8
- group :test do
9
- gem 'guard'
10
- gem 'guard-rspec'
11
- gem 'rb-inotify', require: false
12
- gem 'rb-fsevent', require: false
13
- gem 'rb-fchange', require: false
14
- end
@@ -1,69 +0,0 @@
1
- module ActiveData
2
- module Attributes
3
- class Base
4
- attr_reader :name, :options
5
-
6
- def initialize name, options = {}, &block
7
- @name = name.to_sym
8
- @options = options
9
- @options[:default] = block if block
10
- end
11
-
12
- def type
13
- @type ||= options[:type] || Object
14
- end
15
-
16
- def values
17
- @values ||= options[:in].dup if options[:in]
18
- end
19
-
20
- def default
21
- @default ||= @options[:default]
22
- end
23
-
24
- def default_blank?
25
- @default_blank ||= !!@options[:default_blank]
26
- end
27
-
28
- def default_value instance
29
- default.respond_to?(:call) ? default.call(instance) : default unless default.nil?
30
- end
31
-
32
- def type_cast value
33
- return value if value.instance_of?(type)
34
- type.active_data_type_cast(value)
35
- end
36
-
37
- def generate_instance_methods context
38
- context.class_eval <<-EOS
39
- def #{name}
40
- read_attribute(:#{name})
41
- end
42
-
43
- def #{name}= value
44
- write_attribute(:#{name}, value)
45
- end
46
-
47
- def #{name}?
48
- read_attribute(:#{name}).present?
49
- end
50
-
51
- def #{name}_before_type_cast
52
- read_attribute_before_type_cast(:#{name})
53
- end
54
- EOS
55
- end
56
-
57
- def generate_class_methods context
58
- if values
59
- context.class_eval <<-EOS
60
- def #{name}_values
61
- _attributes[:#{name}].values
62
- end
63
- EOS
64
- end
65
- end
66
-
67
- end
68
- end
69
- end
@@ -1,42 +0,0 @@
1
- module ActiveData
2
- module Attributes
3
- class Localized < Base
4
-
5
- def default_value *args
6
- {}
7
- end
8
-
9
- def generate_instance_methods context
10
- context.class_eval <<-EOS
11
- def #{name}_translations
12
- read_attribute(:#{name})
13
- end
14
-
15
- def #{name}_translations= value
16
- write_attribute(:#{name}, value)
17
- end
18
-
19
- def #{name}
20
- read_localized_attribute(:#{name})
21
- end
22
-
23
- def #{name}= value
24
- write_localized_attribute(:#{name}, value)
25
- end
26
-
27
- def #{name}?
28
- read_localized_attribute(:#{name}).present?
29
- end
30
-
31
- def #{name}_before_type_cast
32
- read_localized_attribute_before_type_cast(:#{name})
33
- end
34
- EOS
35
- end
36
-
37
- def generate_class_methods context
38
- end
39
-
40
- end
41
- end
42
- end
@@ -1,30 +0,0 @@
1
- module ActiveData
2
- module Model
3
- module Associations
4
- class Association
5
- attr_reader :name, :klass, :options
6
-
7
- def initialize name, options = {}
8
- @name, @options = name.to_s, options
9
- @klass ||= options[:class] || (options[:class_name].to_s.presence || name.to_s.classify).safe_constantize
10
- raise "Can not determine class for `#{name}` association" unless @klass
11
- end
12
-
13
- def class_name
14
- klass.to_s
15
- end
16
-
17
- def define_accessor klass
18
- define_reader klass
19
- define_writer klass
20
- end
21
-
22
- def define_reader klass
23
- end
24
-
25
- def define_writer klass
26
- end
27
- end
28
- end
29
- end
30
- end
@@ -1,122 +0,0 @@
1
- module ActiveData
2
- module Model
3
- module Attributable
4
- extend ActiveSupport::Concern
5
-
6
- included do
7
- class_attribute :_attributes, :instance_reader => false, :instance_writer => false
8
- self._attributes = {}
9
-
10
- delegate :attribute_default, :to => 'self.class'
11
- end
12
-
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
-
23
- def build_attribute name, options = {}, &block
24
- klass = case options[:type].to_s
25
- when 'Localized'
26
- ActiveData::Attributes::Localized
27
- else
28
- ActiveData::Attributes::Base
29
- end
30
- klass.new name, options, &block
31
- end
32
-
33
- def generated_class_attributes_methods
34
- @generated_class_attributes_methods ||= Module.new.tap { |proxy| extend proxy }
35
- end
36
-
37
- def generated_instance_attributes_methods
38
- @generated_instance_attributes_methods ||= Module.new.tap { |proxy| include proxy }
39
- end
40
-
41
- def initialize_attributes
42
- Hash[_attributes.map { |(name, _)| [name, nil] }]
43
- end
44
- end
45
-
46
- def read_attribute name
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.respond_to?(:empty?) ? value.empty? : value.nil?
54
- attributes_cache[name] = use_default ? attribute.default_value(self) : value
55
- end
56
- end
57
- alias_method :[], :read_attribute
58
-
59
- def has_attribute? name
60
- @attributes.key? name.to_sym
61
- end
62
-
63
- def read_attribute_before_type_cast name
64
- @attributes[name.to_sym]
65
- end
66
-
67
- def write_attribute name, value
68
- name = name.to_sym
69
- attributes_cache.delete name
70
- @attributes[name] = value
71
- end
72
- alias_method :[]=, :write_attribute
73
-
74
- def attributes
75
- Hash[attribute_names.map { |name| [name, send(name)] }]
76
- end
77
-
78
- def present_attributes
79
- Hash[attribute_names.map do |name|
80
- value = send(name)
81
- [name, value] unless value.respond_to?(:empty?) ? value.empty? : value.nil?
82
- end.compact]
83
- end
84
-
85
- def attribute_names
86
- @attributes.keys
87
- end
88
-
89
- def attributes= attributes
90
- assign_attributes(attributes)
91
- end
92
- alias_method :update_attributes, :attributes=
93
-
94
- def write_attributes attributes
95
- attributes.each { |(name, value)| send("#{name}=", value) }
96
- end
97
-
98
- def reverse_update_attributes attributes
99
- reverse_assign_attributes(attributes)
100
- end
101
-
102
- private
103
-
104
- def attributes_cache
105
- @attributes_cache ||= {}
106
- end
107
-
108
- def assign_attributes attributes
109
- (attributes.presence || {}).each do |(name, value)|
110
- send("#{name}=", value) if has_attribute?(name) || respond_to?("#{name}=")
111
- end
112
- end
113
-
114
- def reverse_assign_attributes attributes
115
- (attributes.presence || {}).each do |(name, value)|
116
- send("#{name}=", value) if respond_to?("#{name}=") && respond_to?(name) && send(name).blank?
117
- end
118
- end
119
-
120
- end
121
- end
122
- end
@@ -1,55 +0,0 @@
1
- require 'active_data/model/collectionizable/proxy'
2
-
3
- module ActiveData
4
- module Model
5
- module Collectionizable
6
- extend ActiveSupport::Concern
7
-
8
- included do
9
- class_attribute :_collection_superclass
10
- collectionize
11
- end
12
-
13
- module ClassMethods
14
-
15
- def collectionize collection_superclass = Array
16
- self._collection_superclass = collection_superclass
17
- end
18
-
19
- def respond_to_missing? method, include_private
20
- super || collection_class.superclass.method_defined?(method)
21
- end
22
-
23
- def method_missing method, *args, &block
24
- collection_class.superclass.method_defined?(method) ?
25
- current_scope.send(method, *args, &block) :
26
- super
27
- end
28
-
29
- def collection source = nil
30
- collection_class.new source
31
- end
32
-
33
- def 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
39
- end
40
-
41
- def current_scope= value
42
- @current_scope = value
43
- end
44
-
45
- def current_scope
46
- @current_scope ||= collection(load)
47
- end
48
- alias :scope :current_scope
49
-
50
- def load; end
51
-
52
- end
53
- end
54
- end
55
- end
@@ -1,42 +0,0 @@
1
- module ActiveData
2
- module Model
3
- module Collectionizable
4
- module Proxy
5
- extend ActiveSupport::Concern
6
-
7
- included do
8
- class_attribute :collectible
9
-
10
- def initialize source = nil
11
- source ||= self.class.superclass.new
12
- super source.map { |entity| collectible.instantiate(entity) }
13
- end
14
- end
15
-
16
- def respond_to? method
17
- super || collectible.respond_to?(method)
18
- end
19
-
20
- def method_missing method, *args, &block
21
- result = with_scope { collectible.send(method, *args, &block) }
22
- result = self.class.new result if result.instance_of? self.class.superclass
23
- result
24
- end
25
-
26
- def with_scope
27
- previous_scope = collectible.current_scope
28
- collectible.current_scope = self
29
- result = yield
30
- collectible.current_scope = previous_scope
31
- result
32
- end
33
-
34
- module ClassMethods
35
- def active_data_type_cast value
36
- new value
37
- end
38
- end
39
- end
40
- end
41
- end
42
- end
@@ -1,9 +0,0 @@
1
- unless defined?(Boolean)
2
- class Boolean; end
3
- end
4
-
5
- unless defined?(Localized)
6
- class Localized; end
7
- end
8
-
9
- Dir["#{File.dirname(__FILE__)}/extensions/*.rb"].each { |f| require f }
@@ -1,24 +0,0 @@
1
- module ActiveData
2
- module Model
3
- module Extensions
4
- module Array
5
- extend ActiveSupport::Concern
6
-
7
- module ClassMethods
8
- def active_data_type_cast value
9
- case value
10
- when ::Array then
11
- value
12
- when ::String then
13
- value.split(',').map(&:strip)
14
- else
15
- nil
16
- end
17
- end
18
- end
19
- end
20
- end
21
- end
22
- end
23
-
24
- Array.send :include, ActiveData::Model::Extensions::Array
@@ -1,17 +0,0 @@
1
- module ActiveData
2
- module Model
3
- module Extensions
4
- module BigDecimal
5
- extend ActiveSupport::Concern
6
-
7
- module ClassMethods
8
- def active_data_type_cast value
9
- ::BigDecimal.new Float(value).to_s rescue nil if value
10
- end
11
- end
12
- end
13
- end
14
- end
15
- end
16
-
17
- BigDecimal.send :include, ActiveData::Model::Extensions::BigDecimal
@@ -1,38 +0,0 @@
1
- module ActiveData
2
- module Model
3
- module Extensions
4
- module Boolean
5
- extend ActiveSupport::Concern
6
-
7
- MAPPING = {
8
- 1 => true,
9
- 0 => false,
10
- '1' => true,
11
- '0' => false,
12
- 't' => true,
13
- 'f' => false,
14
- 'T' => true,
15
- 'F' => false,
16
- true => true,
17
- false => false,
18
- 'true' => true,
19
- 'false' => false,
20
- 'TRUE' => true,
21
- 'FALSE' => false,
22
- 'y' => true,
23
- 'n' => false,
24
- 'yes' => true,
25
- 'no' => false,
26
- }
27
-
28
- module ClassMethods
29
- def active_data_type_cast value
30
- MAPPING[value]
31
- end
32
- end
33
- end
34
- end
35
- end
36
- end
37
-
38
- Boolean.send :include, ActiveData::Model::Extensions::Boolean