options_model 0.0.1 → 0.0.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bbc86cf05d36942bfaedc8e5110ffde4560dec33
4
- data.tar.gz: 51d723a133527412281c1751da1269cff2e6eb13
3
+ metadata.gz: 68ef05d17124810d0f70c7c6f08e996045d455dd
4
+ data.tar.gz: 4b0511272bf4303dff6a6ae0b87d149e3074cee4
5
5
  SHA512:
6
- metadata.gz: 349f91af8fe2bdc272af7fd56ba0f307a798e9bfc14b13c28216ea0ca5c07551cc6fecba7f130171e61328c84352c9415cdcd66a897b3eed276d6f4834d39b9c
7
- data.tar.gz: 41fb67f98b8ca797a0a7d97985694eceadbc419dd03db1141cecf07643efd81eb9227c4e6530d8890f53ffde9a93390f015082725987e90d30a92b3a31af5349
6
+ metadata.gz: 17ce123c0378e081b1c49298b4666f357677b77d1bd8d7faf431bef6bcbe38516aabbdc31c35982c6f6e26265d1bb4e7288d5ffd30e5bddb98a419dea0bcc11a
7
+ data.tar.gz: c487d6352c9a9d749aa3d5165776398733af9e44f05cf406169765158edde4f272953271549db831cf559ca83a18d51fe170a72e54d9b87afa15f1708073257a
@@ -1,77 +1,79 @@
1
- module OptionsModel::Concerns
2
- module AttributeAssignment
3
- extend ActiveSupport::Concern
1
+ module OptionsModel
2
+ module Concerns
3
+ module AttributeAssignment
4
+ extend ActiveSupport::Concern
4
5
 
5
- def initialize(attributes = {})
6
- update_attributes(attributes)
7
- end
6
+ def initialize(attributes = {})
7
+ update_attributes(attributes)
8
+ end
8
9
 
9
- def initialize_dup(other)
10
- super
10
+ def initialize_dup(other)
11
+ super
11
12
 
12
- update_attributes(other)
13
- end
13
+ update_attributes(other)
14
+ end
14
15
 
15
- def update_attributes(other)
16
- return unless other
16
+ def update_attributes(other)
17
+ return unless other
17
18
 
18
- unless other.respond_to?(:to_h)
19
- raise ArgumentError, "#{other} must be respond to `to_h`"
20
- end
19
+ unless other.respond_to?(:to_h)
20
+ raise ArgumentError, "#{other} must be respond to `to_h`"
21
+ end
21
22
 
22
- other.to_h.each do |k, v|
23
- if respond_to?("#{k}=")
24
- public_send("#{k}=", v)
25
- else
26
- unused_attributes[k] = v
23
+ other.to_h.each do |k, v|
24
+ if respond_to?("#{k}=")
25
+ public_send("#{k}=", v)
26
+ else
27
+ unused_attributes[k] = v
28
+ end
27
29
  end
28
30
  end
29
- end
30
31
 
31
- def [](key)
32
- public_send(key) if respond_to?(key)
33
- end
34
-
35
- def []=(key, val)
36
- setter = "#{key}="
37
- if respond_to?(setter)
38
- public_send(setter, val)
39
- else
40
- unused_attributes[key] = val
32
+ def [](key)
33
+ public_send(key) if respond_to?(key)
41
34
  end
42
- end
43
35
 
44
- def fetch(key, default = nil)
45
- if self.class.attribute_names.exclude?(key.to_sym) && default.nil? && !block_given?
46
- raise KeyError, "attribute not found"
36
+ def []=(key, val)
37
+ setter = "#{key}="
38
+ if respond_to?(setter)
39
+ public_send(setter, val)
40
+ else
41
+ unused_attributes[key] = val
42
+ end
47
43
  end
48
44
 
49
- value = respond_to?(key) ? public_send(key) : nil
50
- return value if value
45
+ def fetch(key, default = nil)
46
+ if self.class.attribute_names.exclude?(key.to_sym) && default.nil? && !block_given?
47
+ raise KeyError, "attribute not found"
48
+ end
49
+
50
+ value = respond_to?(key) ? public_send(key) : nil
51
+ return value if value
51
52
 
52
- if default
53
- default
54
- elsif block_given?
55
- yield
53
+ if default
54
+ default
55
+ elsif block_given?
56
+ yield
57
+ end
56
58
  end
57
- end
58
59
 
59
- def _attributes
60
- @attributes ||= ActiveSupport::HashWithIndifferentAccess.new
61
- end
62
- private :_attributes
63
- alias_method :attributes, :_attributes
60
+ def _attributes
61
+ @attributes ||= ActiveSupport::HashWithIndifferentAccess.new
62
+ end
63
+ private :_attributes
64
+ alias_method :attributes, :_attributes
64
65
 
65
- def _nested_attributes
66
- @nested_attributes ||= ActiveSupport::HashWithIndifferentAccess.new
67
- end
68
- private :_nested_attributes
69
- alias_method :nested_attributes, :_nested_attributes
66
+ def _nested_attributes
67
+ @nested_attributes ||= ActiveSupport::HashWithIndifferentAccess.new
68
+ end
69
+ private :_nested_attributes
70
+ alias_method :nested_attributes, :_nested_attributes
70
71
 
71
- def _unused_attributes
72
- @unused_attributes ||= ActiveSupport::HashWithIndifferentAccess.new
72
+ def _unused_attributes
73
+ @unused_attributes ||= ActiveSupport::HashWithIndifferentAccess.new
74
+ end
75
+ private :_unused_attributes
76
+ alias_method :unused_attributes, :_unused_attributes
73
77
  end
74
- private :_unused_attributes
75
- alias_method :unused_attributes, :_unused_attributes
76
78
  end
77
79
  end
@@ -1,30 +1,31 @@
1
- module OptionsModel::Concerns
2
- module Attributes
3
- extend ActiveSupport::Concern
1
+ module OptionsModel
2
+ module Concerns
3
+ module Attributes
4
+ extend ActiveSupport::Concern
4
5
 
5
- module ClassMethods
6
- def attribute(name, cast_type, default: nil, array: false)
7
- check_not_finalized!
6
+ module ClassMethods
7
+ def attribute(name, cast_type, default: nil, array: false)
8
+ check_not_finalized!
8
9
 
9
- name = name.to_sym
10
- check_name_validity! name
10
+ name = name.to_sym
11
+ check_name_validity! name
11
12
 
12
- ActiveModel::Type.lookup(cast_type)
13
+ ActiveModel::Type.lookup(cast_type)
13
14
 
14
- attribute_defaults[name] = default
15
+ attribute_defaults[name] = default
15
16
 
16
- generated_attribute_methods.synchronize do
17
- generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
17
+ generated_attribute_methods.synchronize do
18
+ generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
18
19
  def #{name}
19
20
  value = attributes[:#{name}]
20
21
  return value unless value.nil?
21
22
  attributes[:#{name}] = self.class.attribute_defaults[:#{name}].#{default.respond_to?(:call) ? "call" : "dup"}
22
23
  attributes[:#{name}]
23
24
  end
24
- STR
25
+ STR
25
26
 
26
- if array
27
- generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
27
+ if array
28
+ generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
28
29
  def #{name}=(value)
29
30
  if value.respond_to?(:to_a)
30
31
  attributes[:#{name}] = value.to_a.map { |i| ActiveModel::Type.lookup(:#{cast_type}).cast(i) }
@@ -35,70 +36,70 @@ module OptionsModel::Concerns
35
36
  "`value` should respond to `to_a`, but got \#{value.class} -- \#{value.inspect}"
36
37
  end
37
38
  end
38
- STR
39
- else
40
- generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
39
+ STR
40
+ else
41
+ generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
41
42
  def #{name}=(value)
42
43
  attributes[:#{name}] = ActiveModel::Type.lookup(:#{cast_type}).cast(value)
43
44
  end
44
- STR
45
+ STR
45
46
 
46
- if cast_type == :boolean
47
- generated_attribute_methods.send :alias_method, :"#{name}?", name
47
+ if cast_type == :boolean
48
+ generated_attribute_methods.send :alias_method, :"#{name}?", name
49
+ end
48
50
  end
49
51
  end
50
- end
51
52
 
52
- self.attribute_names_for_inlining << name
53
- name
54
- end
53
+ self.attribute_names_for_inlining << name
54
+ name
55
+ end
55
56
 
56
- def enum_attribute(name, enum, default: nil, allow_nil: false)
57
- check_not_finalized!
57
+ def enum_attribute(name, enum, default: nil, allow_nil: false)
58
+ check_not_finalized!
58
59
 
59
- unless enum.is_a?(Array) && enum.any?
60
- raise ArgumentError, "enum should be an Array and can't empty"
61
- end
62
- enum = enum.map(&:to_s)
60
+ unless enum.is_a?(Array) && enum.any?
61
+ raise ArgumentError, "enum should be an Array and can't empty"
62
+ end
63
+ enum = enum.map(&:to_s)
63
64
 
64
- attribute name, :string, default: default
65
+ attribute name, :string, default: default
65
66
 
66
- pluralized_name = name.to_s.pluralize
67
- generated_class_methods.synchronize do
68
- generated_class_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
67
+ pluralized_name = name.to_s.pluralize
68
+ generated_class_methods.synchronize do
69
+ generated_class_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
69
70
  def #{pluralized_name}
70
71
  %w(#{enum.join(" ")}).freeze
71
72
  end
72
- STR
73
+ STR
73
74
 
74
- validates name, inclusion: {in: enum}, allow_nil: allow_nil
75
+ validates name, inclusion: {in: enum}, allow_nil: allow_nil
76
+ end
75
77
  end
76
- end
77
78
 
78
- def embeds_one(name, class_name: nil, anonymous_class: nil)
79
- check_not_finalized!
79
+ def embeds_one(name, class_name: nil, anonymous_class: nil)
80
+ check_not_finalized!
80
81
 
81
- if class_name.blank? && anonymous_class.nil?
82
- raise ArgumentError, "must provide at least one of `class_name` or `anonymous_class`"
83
- end
82
+ if class_name.blank? && anonymous_class.nil?
83
+ raise ArgumentError, "must provide at least one of `class_name` or `anonymous_class`"
84
+ end
84
85
 
85
- name = name.to_sym
86
- check_name_validity! name
86
+ name = name.to_sym
87
+ check_name_validity! name
87
88
 
88
- if class_name.present?
89
- nested_classes[name] = class_name.constantize
90
- else
91
- nested_classes[name] = anonymous_class
92
- end
89
+ if class_name.present?
90
+ nested_classes[name] = class_name.constantize
91
+ else
92
+ nested_classes[name] = anonymous_class
93
+ end
93
94
 
94
- generated_attribute_methods.synchronize do
95
- generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
95
+ generated_attribute_methods.synchronize do
96
+ generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
96
97
  def #{name}
97
98
  nested_attributes[:#{name}] ||= self.class.nested_classes[:#{name}].new(attributes[:#{name}])
98
99
  end
99
- STR
100
+ STR
100
101
 
101
- generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
102
+ generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
102
103
  def #{name}=(value)
103
104
  klass = self.class.nested_classes[:#{name}]
104
105
  if value.respond_to?(:to_h)
@@ -112,91 +113,92 @@ module OptionsModel::Concerns
112
113
  "`value` should respond to `to_h` or \#{klass}, but got \#{value.class}"
113
114
  end
114
115
  end
115
- STR
116
+ STR
117
+ end
118
+
119
+ self.attribute_names_for_nesting << name
120
+ name
116
121
  end
117
122
 
118
- self.attribute_names_for_nesting << name
119
- name
120
- end
123
+ def attribute_defaults
124
+ @attribute_defaults ||= ActiveSupport::HashWithIndifferentAccess.new
125
+ end
121
126
 
122
- def attribute_defaults
123
- @attribute_defaults ||= ActiveSupport::HashWithIndifferentAccess.new
124
- end
127
+ def nested_classes
128
+ @nested_classes ||= ActiveSupport::HashWithIndifferentAccess.new
129
+ end
125
130
 
126
- def nested_classes
127
- @nested_classes ||= ActiveSupport::HashWithIndifferentAccess.new
128
- end
131
+ def attribute_names_for_nesting
132
+ @attribute_names_for_nesting ||= Set.new
133
+ end
129
134
 
130
- def attribute_names_for_nesting
131
- @attribute_names_for_nesting ||= Set.new
132
- end
135
+ def attribute_names_for_inlining
136
+ @attribute_names_for_inlining ||= Set.new
137
+ end
133
138
 
134
- def attribute_names_for_inlining
135
- @attribute_names_for_inlining ||= Set.new
136
- end
139
+ def attribute_names
140
+ attribute_names_for_nesting + attribute_names_for_inlining
141
+ end
137
142
 
138
- def attribute_names
139
- attribute_names_for_nesting + attribute_names_for_inlining
140
- end
143
+ def finalized?
144
+ @finalized ||= false
145
+ end
141
146
 
142
- def finalized?
143
- @finalized ||= false
144
- end
147
+ def finalize!(nested = true)
148
+ if nested
149
+ nested_classes.values.each &:finalize!
150
+ end
145
151
 
146
- def finalize!(nested = true)
147
- if nested
148
- nested_classes.values.each &:finalize!
152
+ @finalized = true
149
153
  end
150
154
 
151
- @finalized = true
152
- end
155
+ protected
153
156
 
154
- protected
157
+ def check_name_validity!(symbolized_name)
158
+ if dangerous_attribute_method?(symbolized_name)
159
+ raise ArgumentError, "#{symbolized_name} is defined by #{OptionsModel::Base}. Check to make sure that you don't have an attribute or method with the same name."
160
+ end
155
161
 
156
- def check_name_validity!(symbolized_name)
157
- if dangerous_attribute_method?(symbolized_name)
158
- raise ArgumentError, "#{symbolized_name} is defined by #{OptionsModel::Base}. Check to make sure that you don't have an attribute or method with the same name."
162
+ if attribute_names_for_inlining.include?(symbolized_name) || attribute_names_for_nesting.include?(symbolized_name)
163
+ raise ArgumentError, "duplicate define attribute `#{symbolized_name}`"
164
+ end
159
165
  end
160
166
 
161
- if attribute_names_for_inlining.include?(symbolized_name) || attribute_names_for_nesting.include?(symbolized_name)
162
- raise ArgumentError, "duplicate define attribute `#{symbolized_name}`"
167
+ def check_not_finalized!
168
+ if finalized?
169
+ raise "can't modify finalized #{self}"
170
+ end
163
171
  end
164
- end
165
172
 
166
- def check_not_finalized!
167
- if finalized?
168
- raise "can't modify finalized #{self}"
173
+ # A method name is 'dangerous' if it is already (re)defined by OptionsModel, but
174
+ # not by any ancestors. (So 'puts' is not dangerous but 'save' is.)
175
+ def dangerous_attribute_method?(name) # :nodoc:
176
+ method_defined_within?(name, OptionsModel::Base)
169
177
  end
170
- end
171
178
 
172
- # A method name is 'dangerous' if it is already (re)defined by OptionsModel, but
173
- # not by any ancestors. (So 'puts' is not dangerous but 'save' is.)
174
- def dangerous_attribute_method?(name) # :nodoc:
175
- method_defined_within?(name, OptionsModel::Base)
176
- end
177
-
178
- def method_defined_within?(name, klass, superklass = klass.superclass) # :nodoc:
179
- if klass.method_defined?(name) || klass.private_method_defined?(name)
180
- if superklass.method_defined?(name) || superklass.private_method_defined?(name)
181
- klass.instance_method(name).owner != superklass.instance_method(name).owner
179
+ def method_defined_within?(name, klass, superklass = klass.superclass) # :nodoc:
180
+ if klass.method_defined?(name) || klass.private_method_defined?(name)
181
+ if superklass.method_defined?(name) || superklass.private_method_defined?(name)
182
+ klass.instance_method(name).owner != superklass.instance_method(name).owner
183
+ else
184
+ true
185
+ end
182
186
  else
183
- true
187
+ false
184
188
  end
185
- else
186
- false
187
189
  end
188
- end
189
190
 
190
- def generated_attribute_methods
191
- @generated_attribute_methods ||= Module.new {
192
- extend Mutex_m
193
- }.tap { |mod| include mod }
194
- end
191
+ def generated_attribute_methods
192
+ @generated_attribute_methods ||= Module.new {
193
+ extend Mutex_m
194
+ }.tap { |mod| include mod }
195
+ end
195
196
 
196
- def generated_class_methods
197
- @generated_class_methods ||= Module.new {
198
- extend Mutex_m
199
- }.tap { |mod| extend mod }
197
+ def generated_class_methods
198
+ @generated_class_methods ||= Module.new {
199
+ extend Mutex_m
200
+ }.tap { |mod| extend mod }
201
+ end
200
202
  end
201
203
  end
202
204
  end
@@ -1,18 +1,20 @@
1
- module OptionsModel::Concerns
2
- module NameHacking
3
- extend ActiveSupport::Concern
1
+ module OptionsModel
2
+ module Concerns
3
+ module NameHacking
4
+ extend ActiveSupport::Concern
4
5
 
5
- module ClassMethods
6
- def name
7
- @_name
8
- end
9
-
10
- def name=(value)
11
- unless /^[A-Z][a-zA-Z_0-9]*$/ =~ value
12
- raise ArgumentError, "`name` must a valid class name"
6
+ module ClassMethods
7
+ def name
8
+ @_name
13
9
  end
14
10
 
15
- @_name = value
11
+ def name=(value)
12
+ unless /^[A-Z][a-zA-Z_0-9]*$/ =~ value
13
+ raise ArgumentError, "`name` must a valid class name"
14
+ end
15
+
16
+ @_name = value
17
+ end
16
18
  end
17
19
  end
18
20
  end
@@ -1,50 +1,52 @@
1
- module OptionsModel::Concerns
2
- module Serialization
3
- extend ActiveSupport::Concern
4
-
5
- def to_h
6
- hash = {}
7
-
8
- self.class.attribute_names.each do |attribute_name|
9
- attribute = public_send(attribute_name)
10
- if attribute.is_a?(OptionsModel::Base)
11
- hash[attribute_name] = attribute.to_h
12
- else
13
- hash[attribute_name] = attribute
1
+ module OptionsModel
2
+ module Concerns
3
+ module Serialization
4
+ extend ActiveSupport::Concern
5
+
6
+ def to_h
7
+ hash = {}
8
+
9
+ self.class.attribute_names.each do |attribute_name|
10
+ attribute = public_send(attribute_name)
11
+ if attribute.is_a?(OptionsModel::Base)
12
+ hash[attribute_name] = attribute.to_h
13
+ else
14
+ hash[attribute_name] = attribute
15
+ end
14
16
  end
17
+
18
+ hash
15
19
  end
16
20
 
17
- hash
18
- end
21
+ def to_h_with_unused
22
+ to_h.merge unused_attributes
23
+ end
19
24
 
20
- def to_h_with_unused
21
- to_h.merge unused_attributes
22
- end
25
+ module ClassMethods
26
+ def dump(obj)
27
+ return YAML.dump({}) unless obj
23
28
 
24
- module ClassMethods
25
- def dump(obj)
26
- return YAML.dump({}) unless obj
29
+ unless obj.is_a? self
30
+ raise ArgumentError,
31
+ "can't dump: was supposed to be a #{self}, but was a #{obj.class}. -- #{obj.inspect}"
32
+ end
27
33
 
28
- unless obj.is_a? self
29
- raise ArgumentError,
30
- "can't dump: was supposed to be a #{self}, but was a #{obj.class}. -- #{obj.inspect}"
34
+ YAML.dump obj.to_h
31
35
  end
32
36
 
33
- YAML.dump obj.to_h
34
- end
37
+ def load(yaml)
38
+ return new unless yaml
39
+ return new unless yaml.is_a?(String) && /^---/.match?(yaml)
35
40
 
36
- def load(yaml)
37
- return new unless yaml
38
- return new unless yaml.is_a?(String) && /^---/.match?(yaml)
41
+ hash = YAML.load(yaml) || Hash.new
39
42
 
40
- hash = YAML.load(yaml) || Hash.new
43
+ unless hash.is_a? Hash
44
+ raise ArgumentError,
45
+ "can't load: was supposed to be a #{Hash}, but was a #{hash.class}. -- #{hash.inspect}"
46
+ end
41
47
 
42
- unless hash.is_a? Hash
43
- raise ArgumentError,
44
- "can't load: was supposed to be a #{Hash}, but was a #{hash.class}. -- #{hash.inspect}"
48
+ new hash
45
49
  end
46
-
47
- new hash
48
50
  end
49
51
  end
50
52
  end
@@ -1,3 +1,3 @@
1
1
  module OptionsModel
2
- VERSION = "0.0.1".freeze
2
+ VERSION = "0.0.2".freeze
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: options_model
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - jasl