options_model 0.0.1 → 0.0.2

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