opium 1.2.0 → 1.2.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 +4 -4
- data/CHANGELOG.md +8 -0
- data/lib/opium/model/field.rb +4 -0
- data/lib/opium/model/fieldable.rb +41 -28
- data/lib/opium/model/relation.rb +32 -23
- data/lib/opium/model.rb +1 -0
- data/lib/opium/version.rb +1 -1
- data/spec/opium/model/relatable_spec.rb +28 -0
- data/spec/opium/model/relation_spec.rb +16 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ecd9332e3c5b659bcb498c22bd08e109dab91b84
|
4
|
+
data.tar.gz: e9f1feaa43921e23339c2ea17905ed6f9470e796
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4aa3f212aa8ab6d3a23994909f05d34df0aa7b7b767fb192946a7a2ed1f764758ad594b3ea199bf086296460cc2aeebda4864c62b1dd7911bcdcf7e5b8aeb1fb
|
7
|
+
data.tar.gz: ba8ccb1d384ead2549edfa4d58f9c8d852812a1081d20b301aee0c82ff742f28cbd2bec45f5a652e2474047ed3c4c8c333b235c70473d322953ba4b89839968e
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
## 1.2.1
|
2
|
+
### New Features
|
3
|
+
- Fieldable should now be refactored to be more readable and less cluttered; .field, in particular, has been split up into a set of algorithmic steps.
|
4
|
+
- #45: If GlobalID is defined, it is automatically included into all models.
|
5
|
+
|
6
|
+
### Resolved Issues
|
7
|
+
- #46: Relations should now more gracefully handle conversions from nil and Array.
|
8
|
+
|
1
9
|
## 1.2.0
|
2
10
|
### New Features
|
3
11
|
- #33: Model associations.
|
data/lib/opium/model/field.rb
CHANGED
@@ -13,31 +13,10 @@ module Opium
|
|
13
13
|
|
14
14
|
module ClassMethods
|
15
15
|
def field( name, options = {} )
|
16
|
-
name
|
17
|
-
|
18
|
-
|
19
|
-
parse_canonical_field_names[name] = parse_canonical_field_names[fields[name].name_to_parse] = fields[name].name_to_parse.to_s
|
20
|
-
class_eval do
|
21
|
-
define_attribute_methods [name]
|
22
|
-
define_method(name) do
|
23
|
-
self.attributes[name]
|
24
|
-
end
|
25
|
-
end
|
26
|
-
unless self.respond_to? "#{name}="
|
27
|
-
class_eval do
|
28
|
-
define_method("#{name}=") do |value|
|
29
|
-
converted = self.class.fields[name].type.to_ruby(value)
|
30
|
-
send( "#{name}_will_change!" ) unless self.attributes[name] == converted
|
31
|
-
if self.class.fields[name].relation?
|
32
|
-
converted.owner ||= self
|
33
|
-
converted.metadata ||= self.class.relations[name]
|
34
|
-
end
|
35
|
-
self.attributes[name] = converted
|
36
|
-
end
|
37
|
-
send(:private, "#{name}=") if options[:readonly]
|
38
|
-
end
|
16
|
+
create_field_from( name.to_sym, options ).tap do |field|
|
17
|
+
create_field_getter_for( field )
|
18
|
+
create_field_setter_for( field )
|
39
19
|
end
|
40
|
-
fields[name]
|
41
20
|
end
|
42
21
|
|
43
22
|
def has_field?( field_name )
|
@@ -47,19 +26,53 @@ module Opium
|
|
47
26
|
alias_method :field?, :has_field?
|
48
27
|
|
49
28
|
def fields
|
50
|
-
@fields ||=
|
29
|
+
@fields ||= {}.with_indifferent_access
|
51
30
|
end
|
52
31
|
|
53
32
|
def ruby_canonical_field_names
|
54
|
-
@ruby_canonical_field_names ||=
|
33
|
+
@ruby_canonical_field_names ||= {}.with_indifferent_access
|
55
34
|
end
|
56
35
|
|
57
36
|
def parse_canonical_field_names
|
58
|
-
@parse_canonical_field_names ||=
|
37
|
+
@parse_canonical_field_names ||= {}.with_indifferent_access
|
59
38
|
end
|
60
39
|
|
61
40
|
def default_attributes( context = nil )
|
62
|
-
fields.transform_values {|field| field.
|
41
|
+
fields.transform_values {|field| field.contextual_default_value( context ) }.with_indifferent_access
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def create_field_from( name, options )
|
47
|
+
field = Field.new( name, options[:type] || Object, options[:default], options[:readonly] || false, options[:as] )
|
48
|
+
ruby_canonical_field_names[name] = ruby_canonical_field_names[field.name_to_parse] = name.to_s
|
49
|
+
parse_canonical_field_names[name] = parse_canonical_field_names[field.name_to_parse] = field.name_to_parse.to_s
|
50
|
+
fields[name] = field
|
51
|
+
end
|
52
|
+
|
53
|
+
def create_field_getter_for( field )
|
54
|
+
class_eval do
|
55
|
+
define_attribute_methods [field.name]
|
56
|
+
define_method(field.name) do
|
57
|
+
self.attributes[field.name]
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def create_field_setter_for( field )
|
63
|
+
class_eval do
|
64
|
+
define_method("#{ field.name }=") do |value|
|
65
|
+
converted = field.type.to_ruby(value)
|
66
|
+
send( "#{ field.name }_will_change!" ) unless self.attributes[field.name] == converted
|
67
|
+
if field.relation?
|
68
|
+
converted = field.contextual_default_value( self ) unless converted
|
69
|
+
converted.owner ||= self
|
70
|
+
converted.metadata ||= self.class.relations[field.name]
|
71
|
+
end
|
72
|
+
self.attributes[field.name] = converted
|
73
|
+
end
|
74
|
+
send(:private, "#{ field.name }=") if field.readonly?
|
75
|
+
end
|
63
76
|
end
|
64
77
|
end
|
65
78
|
end
|
data/lib/opium/model/relation.rb
CHANGED
@@ -5,46 +5,55 @@ module Opium
|
|
5
5
|
|
6
6
|
class << self
|
7
7
|
def to_parse( object )
|
8
|
-
class_name =
|
9
|
-
case object
|
10
|
-
when Hash
|
11
|
-
fetch_hash_key_from( object, 'class_name' ) || fetch_hash_key_from( object, 'model_name' )
|
12
|
-
when String, Symbol
|
13
|
-
object
|
14
|
-
when is_descendant.curry[Opium::Model]
|
15
|
-
object.model_name
|
16
|
-
when self
|
17
|
-
object.class_name
|
18
|
-
else
|
19
|
-
fail ArgumentError, "could not convert #{ object.inspect } to a parse Relation hash"
|
20
|
-
end
|
8
|
+
class_name = determine_class_name_from( object, 'parse Relation hash' )
|
21
9
|
fail ArgumentError, "could not determine class_name from #{ object.inspect }" unless class_name
|
22
10
|
{ __type: 'Relation', className: class_name }.with_indifferent_access
|
23
11
|
end
|
24
12
|
|
25
13
|
def to_ruby( object )
|
26
|
-
return if object.nil?
|
14
|
+
return if object.nil? || object == []
|
27
15
|
return object if object.is_a? self
|
28
|
-
class_name =
|
16
|
+
class_name = determine_class_name_from( object, self.name )
|
17
|
+
new( class_name ).tap do |relation|
|
29
18
|
case object
|
30
|
-
when
|
31
|
-
fetch_hash_key_from( object, 'class_name' ) || fetch_hash_key_from( object, 'model_name' )
|
32
|
-
when String, Symbol
|
33
|
-
object
|
19
|
+
when String
|
34
20
|
when is_descendant.curry[Opium::Model]
|
35
|
-
object
|
36
|
-
|
37
|
-
|
21
|
+
relation.push object
|
22
|
+
when contains_descendant.curry[Opium::Model]
|
23
|
+
object.select(&is_descendant.curry[Opium::Model]).each {|model| relation.push model}
|
38
24
|
end
|
39
|
-
|
25
|
+
end
|
40
26
|
end
|
41
27
|
|
42
28
|
private
|
43
29
|
|
30
|
+
def determine_class_name_from( object, context )
|
31
|
+
case object
|
32
|
+
when Hash
|
33
|
+
fetch_hash_key_from( object, 'class_name' ) || fetch_hash_key_from( object, 'model_name' )
|
34
|
+
when String, Symbol
|
35
|
+
object
|
36
|
+
when is_descendant.curry[Opium::Model]
|
37
|
+
object.model_name
|
38
|
+
when contains_descendant.curry[Opium::Model]
|
39
|
+
object.select(&is_descendant.curry[Opium::Model]).first.model_name
|
40
|
+
when self
|
41
|
+
object.class_name
|
42
|
+
else
|
43
|
+
fail ArgumentError, "could not convert #{ object.inspect } to a #{ context }"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
44
47
|
def is_descendant
|
45
48
|
@is_descendant ||= ->( expected_type, object ) { ( object.is_a?( Class ) ? object : object.class ) <= expected_type }
|
46
49
|
end
|
47
50
|
|
51
|
+
def contains_descendant
|
52
|
+
@contains_descendant ||= ->( expected_type, object ) do
|
53
|
+
object.is_a?( Enumerable ) ? object.any?( &is_descendant.curry[expected_type] ) : is_descendant.curry[expected_type]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
48
57
|
def fetch_hash_key_from( hash, key )
|
49
58
|
snake_case_key = key.to_s.underscore
|
50
59
|
lower_camel_key = key.to_s.camelcase(:lower)
|
data/lib/opium/model.rb
CHANGED
data/lib/opium/version.rb
CHANGED
@@ -161,6 +161,34 @@ describe Opium::Model::Relatable do
|
|
161
161
|
it { expect( subject.comments ).to_not be_empty }
|
162
162
|
it { expect( subject.comments.owner ).to eq subject }
|
163
163
|
end
|
164
|
+
|
165
|
+
context "when setting a model's relation" do
|
166
|
+
subject { Article.new id: 'abcd1234' }
|
167
|
+
let(:result) { subject.comments = new_value; subject.comments }
|
168
|
+
|
169
|
+
context 'to nil' do
|
170
|
+
let(:new_value) { nil }
|
171
|
+
|
172
|
+
it { expect { result }.to_not raise_exception }
|
173
|
+
it { expect( result ).to be_a Opium::Model::Relation }
|
174
|
+
end
|
175
|
+
|
176
|
+
context 'to []' do
|
177
|
+
let(:new_value) { [] }
|
178
|
+
|
179
|
+
it { expect { result }.to_not raise_exception }
|
180
|
+
it { expect( result ).to be_a Opium::Model::Relation }
|
181
|
+
end
|
182
|
+
|
183
|
+
context 'to an array of models' do
|
184
|
+
let(:comment) { Comment.new }
|
185
|
+
let(:new_value) { [ comment ] }
|
186
|
+
|
187
|
+
it { expect { result }.to_not raise_exception }
|
188
|
+
it { expect( result ).to be_a Opium::Model::Relation }
|
189
|
+
it { expect( result ).to include( comment ) }
|
190
|
+
end
|
191
|
+
end
|
164
192
|
end
|
165
193
|
|
166
194
|
describe '.has_one' do
|
@@ -87,6 +87,22 @@ describe Opium::Model::Relation do
|
|
87
87
|
it { expect( result ).to be_nil }
|
88
88
|
end
|
89
89
|
|
90
|
+
context 'with an empty array' do
|
91
|
+
let(:convert_from) { [] }
|
92
|
+
|
93
|
+
it { expect { result }.to_not raise_exception }
|
94
|
+
it { expect( result ).to be_nil }
|
95
|
+
end
|
96
|
+
|
97
|
+
context 'with an array of RelatedClass' do
|
98
|
+
let(:related_object) { RelatedClass.new title: 'a related object' }
|
99
|
+
let(:convert_from) { [ related_object ] }
|
100
|
+
|
101
|
+
it { expect { result }.to_not raise_exception }
|
102
|
+
it { expect( result ).to be_a described_class }
|
103
|
+
it { expect( result ).to include( related_object ) }
|
104
|
+
end
|
105
|
+
|
90
106
|
context 'with any unconvertable value' do
|
91
107
|
let(:convert_from) { 42 }
|
92
108
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: opium
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.2.
|
4
|
+
version: 1.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joshua Bowers
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-05-
|
11
|
+
date: 2015-05-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|