options_model 0.0.1
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 +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +56 -0
- data/Rakefile +33 -0
- data/lib/options_model.rb +13 -0
- data/lib/options_model/base.rb +36 -0
- data/lib/options_model/concerns/attribute_assignment.rb +77 -0
- data/lib/options_model/concerns/attributes.rb +203 -0
- data/lib/options_model/concerns/name_hacking.rb +19 -0
- data/lib/options_model/concerns/serialization.rb +51 -0
- data/lib/options_model/version.rb +3 -0
- data/lib/tasks/options_model_tasks.rake +4 -0
- metadata +98 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: bbc86cf05d36942bfaedc8e5110ffde4560dec33
|
4
|
+
data.tar.gz: 51d723a133527412281c1751da1269cff2e6eb13
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 349f91af8fe2bdc272af7fd56ba0f307a798e9bfc14b13c28216ea0ca5c07551cc6fecba7f130171e61328c84352c9415cdcd66a897b3eed276d6f4834d39b9c
|
7
|
+
data.tar.gz: 41fb67f98b8ca797a0a7d97985694eceadbc419dd03db1141cecf07643efd81eb9227c4e6530d8890f53ffde9a93390f015082725987e90d30a92b3a31af5349
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2017 Jun Jiang
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
# OptionsModel
|
2
|
+
|
3
|
+
An ActiveModel implementation that make easier to handle model which will be serialized in a real model.
|
4
|
+
|
5
|
+
support attribute:
|
6
|
+
|
7
|
+
- all types that `ActiveModel::Type` support
|
8
|
+
- typed array
|
9
|
+
- enum
|
10
|
+
- embeds one
|
11
|
+
|
12
|
+
## Usage
|
13
|
+
|
14
|
+
class Person < OptionsModel::Base
|
15
|
+
attribute :name, :string
|
16
|
+
attribute :age, :integer
|
17
|
+
|
18
|
+
validates :name, presence: true
|
19
|
+
end
|
20
|
+
|
21
|
+
class Book < OptionsModel::Base
|
22
|
+
embeds_one :author, class_name: 'Person'
|
23
|
+
|
24
|
+
attribute :title, :string
|
25
|
+
attribute :tags, :string, array: true
|
26
|
+
attribute :price, :decimal, default: 0
|
27
|
+
attribute :meta, :json, default: {}
|
28
|
+
attribute :bought_at, :datetime, default: -> { Time.new }
|
29
|
+
|
30
|
+
validates :title, presence: true
|
31
|
+
end
|
32
|
+
|
33
|
+
## Installation
|
34
|
+
Add this line to your application's Gemfile:
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
gem 'options_model'
|
38
|
+
```
|
39
|
+
|
40
|
+
And then execute:
|
41
|
+
```bash
|
42
|
+
$ bundle
|
43
|
+
```
|
44
|
+
|
45
|
+
## Contributing
|
46
|
+
|
47
|
+
1. Fork it
|
48
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
49
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
50
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
51
|
+
5. Create new Pull Request
|
52
|
+
|
53
|
+
Please write unit test with your code if necessary.
|
54
|
+
|
55
|
+
## License
|
56
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'rdoc/task'
|
8
|
+
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
11
|
+
rdoc.title = 'OptionsModel'
|
12
|
+
rdoc.options << '--line-numbers'
|
13
|
+
rdoc.rdoc_files.include('README.md')
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
|
20
|
+
|
21
|
+
|
22
|
+
require 'bundler/gem_tasks'
|
23
|
+
|
24
|
+
require 'rake/testtask'
|
25
|
+
|
26
|
+
Rake::TestTask.new(:test) do |t|
|
27
|
+
t.libs << 'test'
|
28
|
+
t.pattern = 'test/**/*_test.rb'
|
29
|
+
t.verbose = false
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
task default: :test
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require "active_model"
|
2
|
+
require "active_model/type"
|
3
|
+
|
4
|
+
require "options_model/concerns/attribute_assignment"
|
5
|
+
require "options_model/concerns/attributes"
|
6
|
+
require "options_model/concerns/name_hacking"
|
7
|
+
require "options_model/concerns/serialization"
|
8
|
+
|
9
|
+
require "options_model/base"
|
10
|
+
|
11
|
+
module OptionsModel
|
12
|
+
|
13
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module OptionsModel
|
2
|
+
class Base
|
3
|
+
include ActiveModel::Model
|
4
|
+
include OptionsModel::Concerns::Serialization
|
5
|
+
include OptionsModel::Concerns::Attributes
|
6
|
+
include OptionsModel::Concerns::AttributeAssignment
|
7
|
+
|
8
|
+
validate do
|
9
|
+
self.class.attribute_names.each do |attribute_name|
|
10
|
+
attribute = public_send(attribute_name)
|
11
|
+
if attribute.is_a?(self.class) && attribute.invalid?
|
12
|
+
errors.add attribute_name, :invalid
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def inspect
|
18
|
+
"#<#{self.class.name}:OptionsModel #{self.to_h}>"
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.inspect
|
22
|
+
"#<#{name}:OptionsModel [#{attribute_names.map(&:inspect).join(', ')}]>"
|
23
|
+
end
|
24
|
+
|
25
|
+
def persisted?
|
26
|
+
true
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.derive(name)
|
30
|
+
Class.new(self) do
|
31
|
+
include OptionsModel::Concerns::NameHacking
|
32
|
+
self.name = name
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
module OptionsModel::Concerns
|
2
|
+
module AttributeAssignment
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
def initialize(attributes = {})
|
6
|
+
update_attributes(attributes)
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize_dup(other)
|
10
|
+
super
|
11
|
+
|
12
|
+
update_attributes(other)
|
13
|
+
end
|
14
|
+
|
15
|
+
def update_attributes(other)
|
16
|
+
return unless other
|
17
|
+
|
18
|
+
unless other.respond_to?(:to_h)
|
19
|
+
raise ArgumentError, "#{other} must be respond to `to_h`"
|
20
|
+
end
|
21
|
+
|
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
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
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
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
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"
|
47
|
+
end
|
48
|
+
|
49
|
+
value = respond_to?(key) ? public_send(key) : nil
|
50
|
+
return value if value
|
51
|
+
|
52
|
+
if default
|
53
|
+
default
|
54
|
+
elsif block_given?
|
55
|
+
yield
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def _attributes
|
60
|
+
@attributes ||= ActiveSupport::HashWithIndifferentAccess.new
|
61
|
+
end
|
62
|
+
private :_attributes
|
63
|
+
alias_method :attributes, :_attributes
|
64
|
+
|
65
|
+
def _nested_attributes
|
66
|
+
@nested_attributes ||= ActiveSupport::HashWithIndifferentAccess.new
|
67
|
+
end
|
68
|
+
private :_nested_attributes
|
69
|
+
alias_method :nested_attributes, :_nested_attributes
|
70
|
+
|
71
|
+
def _unused_attributes
|
72
|
+
@unused_attributes ||= ActiveSupport::HashWithIndifferentAccess.new
|
73
|
+
end
|
74
|
+
private :_unused_attributes
|
75
|
+
alias_method :unused_attributes, :_unused_attributes
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,203 @@
|
|
1
|
+
module OptionsModel::Concerns
|
2
|
+
module Attributes
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
module ClassMethods
|
6
|
+
def attribute(name, cast_type, default: nil, array: false)
|
7
|
+
check_not_finalized!
|
8
|
+
|
9
|
+
name = name.to_sym
|
10
|
+
check_name_validity! name
|
11
|
+
|
12
|
+
ActiveModel::Type.lookup(cast_type)
|
13
|
+
|
14
|
+
attribute_defaults[name] = default
|
15
|
+
|
16
|
+
generated_attribute_methods.synchronize do
|
17
|
+
generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
|
18
|
+
def #{name}
|
19
|
+
value = attributes[:#{name}]
|
20
|
+
return value unless value.nil?
|
21
|
+
attributes[:#{name}] = self.class.attribute_defaults[:#{name}].#{default.respond_to?(:call) ? "call" : "dup"}
|
22
|
+
attributes[:#{name}]
|
23
|
+
end
|
24
|
+
STR
|
25
|
+
|
26
|
+
if array
|
27
|
+
generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
|
28
|
+
def #{name}=(value)
|
29
|
+
if value.respond_to?(:to_a)
|
30
|
+
attributes[:#{name}] = value.to_a.map { |i| ActiveModel::Type.lookup(:#{cast_type}).cast(i) }
|
31
|
+
elsif value.nil?
|
32
|
+
attributes[:#{name}] = self.class.attribute_defaults[:#{name}].#{default.respond_to?(:call) ? "call" : "dup"}
|
33
|
+
else
|
34
|
+
raise ArgumentError,
|
35
|
+
"`value` should respond to `to_a`, but got \#{value.class} -- \#{value.inspect}"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
STR
|
39
|
+
else
|
40
|
+
generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
|
41
|
+
def #{name}=(value)
|
42
|
+
attributes[:#{name}] = ActiveModel::Type.lookup(:#{cast_type}).cast(value)
|
43
|
+
end
|
44
|
+
STR
|
45
|
+
|
46
|
+
if cast_type == :boolean
|
47
|
+
generated_attribute_methods.send :alias_method, :"#{name}?", name
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
self.attribute_names_for_inlining << name
|
53
|
+
name
|
54
|
+
end
|
55
|
+
|
56
|
+
def enum_attribute(name, enum, default: nil, allow_nil: false)
|
57
|
+
check_not_finalized!
|
58
|
+
|
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)
|
63
|
+
|
64
|
+
attribute name, :string, default: default
|
65
|
+
|
66
|
+
pluralized_name = name.to_s.pluralize
|
67
|
+
generated_class_methods.synchronize do
|
68
|
+
generated_class_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
|
69
|
+
def #{pluralized_name}
|
70
|
+
%w(#{enum.join(" ")}).freeze
|
71
|
+
end
|
72
|
+
STR
|
73
|
+
|
74
|
+
validates name, inclusion: {in: enum}, allow_nil: allow_nil
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def embeds_one(name, class_name: nil, anonymous_class: nil)
|
79
|
+
check_not_finalized!
|
80
|
+
|
81
|
+
if class_name.blank? && anonymous_class.nil?
|
82
|
+
raise ArgumentError, "must provide at least one of `class_name` or `anonymous_class`"
|
83
|
+
end
|
84
|
+
|
85
|
+
name = name.to_sym
|
86
|
+
check_name_validity! name
|
87
|
+
|
88
|
+
if class_name.present?
|
89
|
+
nested_classes[name] = class_name.constantize
|
90
|
+
else
|
91
|
+
nested_classes[name] = anonymous_class
|
92
|
+
end
|
93
|
+
|
94
|
+
generated_attribute_methods.synchronize do
|
95
|
+
generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
|
96
|
+
def #{name}
|
97
|
+
nested_attributes[:#{name}] ||= self.class.nested_classes[:#{name}].new(attributes[:#{name}])
|
98
|
+
end
|
99
|
+
STR
|
100
|
+
|
101
|
+
generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
|
102
|
+
def #{name}=(value)
|
103
|
+
klass = self.class.nested_classes[:#{name}]
|
104
|
+
if value.respond_to?(:to_h)
|
105
|
+
nested_attributes[:#{name}] = klass.new(value.to_h)
|
106
|
+
elsif value.is_a? klass
|
107
|
+
nested_attributes[:#{name}] = value
|
108
|
+
elsif value.nil?
|
109
|
+
nested_attributes[:#{name}] = klass.new
|
110
|
+
else
|
111
|
+
raise ArgumentError,
|
112
|
+
"`value` should respond to `to_h` or \#{klass}, but got \#{value.class}"
|
113
|
+
end
|
114
|
+
end
|
115
|
+
STR
|
116
|
+
end
|
117
|
+
|
118
|
+
self.attribute_names_for_nesting << name
|
119
|
+
name
|
120
|
+
end
|
121
|
+
|
122
|
+
def attribute_defaults
|
123
|
+
@attribute_defaults ||= ActiveSupport::HashWithIndifferentAccess.new
|
124
|
+
end
|
125
|
+
|
126
|
+
def nested_classes
|
127
|
+
@nested_classes ||= ActiveSupport::HashWithIndifferentAccess.new
|
128
|
+
end
|
129
|
+
|
130
|
+
def attribute_names_for_nesting
|
131
|
+
@attribute_names_for_nesting ||= Set.new
|
132
|
+
end
|
133
|
+
|
134
|
+
def attribute_names_for_inlining
|
135
|
+
@attribute_names_for_inlining ||= Set.new
|
136
|
+
end
|
137
|
+
|
138
|
+
def attribute_names
|
139
|
+
attribute_names_for_nesting + attribute_names_for_inlining
|
140
|
+
end
|
141
|
+
|
142
|
+
def finalized?
|
143
|
+
@finalized ||= false
|
144
|
+
end
|
145
|
+
|
146
|
+
def finalize!(nested = true)
|
147
|
+
if nested
|
148
|
+
nested_classes.values.each &:finalize!
|
149
|
+
end
|
150
|
+
|
151
|
+
@finalized = true
|
152
|
+
end
|
153
|
+
|
154
|
+
protected
|
155
|
+
|
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."
|
159
|
+
end
|
160
|
+
|
161
|
+
if attribute_names_for_inlining.include?(symbolized_name) || attribute_names_for_nesting.include?(symbolized_name)
|
162
|
+
raise ArgumentError, "duplicate define attribute `#{symbolized_name}`"
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
def check_not_finalized!
|
167
|
+
if finalized?
|
168
|
+
raise "can't modify finalized #{self}"
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
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
|
182
|
+
else
|
183
|
+
true
|
184
|
+
end
|
185
|
+
else
|
186
|
+
false
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
def generated_attribute_methods
|
191
|
+
@generated_attribute_methods ||= Module.new {
|
192
|
+
extend Mutex_m
|
193
|
+
}.tap { |mod| include mod }
|
194
|
+
end
|
195
|
+
|
196
|
+
def generated_class_methods
|
197
|
+
@generated_class_methods ||= Module.new {
|
198
|
+
extend Mutex_m
|
199
|
+
}.tap { |mod| extend mod }
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module OptionsModel::Concerns
|
2
|
+
module NameHacking
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
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"
|
13
|
+
end
|
14
|
+
|
15
|
+
@_name = value
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,51 @@
|
|
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
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
hash
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_h_with_unused
|
21
|
+
to_h.merge unused_attributes
|
22
|
+
end
|
23
|
+
|
24
|
+
module ClassMethods
|
25
|
+
def dump(obj)
|
26
|
+
return YAML.dump({}) unless obj
|
27
|
+
|
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}"
|
31
|
+
end
|
32
|
+
|
33
|
+
YAML.dump obj.to_h
|
34
|
+
end
|
35
|
+
|
36
|
+
def load(yaml)
|
37
|
+
return new unless yaml
|
38
|
+
return new unless yaml.is_a?(String) && /^---/.match?(yaml)
|
39
|
+
|
40
|
+
hash = YAML.load(yaml) || Hash.new
|
41
|
+
|
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}"
|
45
|
+
end
|
46
|
+
|
47
|
+
new hash
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
metadata
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: options_model
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- jasl
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-07-15 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activemodel
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '5.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '5.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: activesupport
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '5.0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '5.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rails
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '5.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '5.0'
|
55
|
+
description: An ActiveModel implementation that make easier to handle model which
|
56
|
+
will be serialized in a real model.
|
57
|
+
email:
|
58
|
+
- jasl9187@hotmail.com
|
59
|
+
executables: []
|
60
|
+
extensions: []
|
61
|
+
extra_rdoc_files: []
|
62
|
+
files:
|
63
|
+
- MIT-LICENSE
|
64
|
+
- README.md
|
65
|
+
- Rakefile
|
66
|
+
- lib/options_model.rb
|
67
|
+
- lib/options_model/base.rb
|
68
|
+
- lib/options_model/concerns/attribute_assignment.rb
|
69
|
+
- lib/options_model/concerns/attributes.rb
|
70
|
+
- lib/options_model/concerns/name_hacking.rb
|
71
|
+
- lib/options_model/concerns/serialization.rb
|
72
|
+
- lib/options_model/version.rb
|
73
|
+
- lib/tasks/options_model_tasks.rake
|
74
|
+
homepage: https://github.com/jasl-lab/options_model
|
75
|
+
licenses:
|
76
|
+
- MIT
|
77
|
+
metadata: {}
|
78
|
+
post_install_message:
|
79
|
+
rdoc_options: []
|
80
|
+
require_paths:
|
81
|
+
- lib
|
82
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
83
|
+
requirements:
|
84
|
+
- - ">="
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: '0'
|
87
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
88
|
+
requirements:
|
89
|
+
- - ">="
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: '0'
|
92
|
+
requirements: []
|
93
|
+
rubyforge_project:
|
94
|
+
rubygems_version: 2.6.12
|
95
|
+
signing_key:
|
96
|
+
specification_version: 4
|
97
|
+
summary: Make easier to handle model which will be serialized in a real model.
|
98
|
+
test_files: []
|