active_type 0.3.5 → 0.4.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.
- checksums.yaml +4 -4
- data/README.md +33 -0
- data/gemfiles/Gemfile.3.2.lock +1 -1
- data/gemfiles/Gemfile.4.0.lock +1 -1
- data/gemfiles/Gemfile.4.1.lock +1 -1
- data/gemfiles/Gemfile.4.2.1.lock +1 -1
- data/gemfiles/Gemfile.4.2.1.pg.lock +1 -1
- data/lib/active_type/util.rb +49 -0
- data/lib/active_type/version.rb +1 -1
- data/lib/active_type.rb +2 -1
- data/spec/active_type/util_spec.rb +128 -0
- metadata +5 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: af57ff59af07cfdb0a8576c733da8aa2d0e254ce
|
|
4
|
+
data.tar.gz: e1e04618118baf2b5260e20ed3685d695930e756
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 91477402f2df135aa9a2bef4a3b63f51c113be820940f83c350230af27b76dcc3c16d587c11874bd64320e1115f68b8fb25c7904e9d6579e3313853fddb8ad08
|
|
7
|
+
data.tar.gz: 7f9fa15fc5ed489c5bee1350f07b97852e32732017c4bb0535d53f4e3fb36c928f20bb9b44dcb5ab6f1ebce5cb892a60e3c382e5e92044e38ef51c823409fb7b
|
data/README.md
CHANGED
|
@@ -271,6 +271,39 @@ Supported options for `nests_many` / `nests_one` are:
|
|
|
271
271
|
```
|
|
272
272
|
|
|
273
273
|
|
|
274
|
+
Casting
|
|
275
|
+
-------
|
|
276
|
+
|
|
277
|
+
When working with ActiveType you will often find it useful to cast an ActiveRecord instance to its extended `ActiveType::Record` variant.
|
|
278
|
+
|
|
279
|
+
Use `ActiveType.cast` for this:
|
|
280
|
+
|
|
281
|
+
```
|
|
282
|
+
class User < ActiveRecord::Base
|
|
283
|
+
...
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
class SignUp < ActiveType::Record[User]
|
|
287
|
+
...
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
user = User.find(1)
|
|
291
|
+
sign_up = ActiveType.cast(SignUp)
|
|
292
|
+
sign_up.is_a?(SignUp) # => true
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
This is basically like [`ActiveRecord#becomes`](http://apidock.com/rails/v4.2.1/ActiveRecord/Persistence/becomes), but with less bugs and more consistent behavior.
|
|
296
|
+
|
|
297
|
+
You can also cast an entire relation (scope) to a relation of an `ActiveType::Record`:
|
|
298
|
+
|
|
299
|
+
```
|
|
300
|
+
adult_users = User.where('age >= 18')
|
|
301
|
+
adult_sign_ups = ActiveType.cast(adult_users, SignUp)
|
|
302
|
+
sign_up = adult_sign_ups.find(1)
|
|
303
|
+
sign_up.is_a?(SignUp) # => true
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
|
|
274
307
|
Supported Rails versions
|
|
275
308
|
------------------------
|
|
276
309
|
|
data/gemfiles/Gemfile.3.2.lock
CHANGED
data/gemfiles/Gemfile.4.0.lock
CHANGED
data/gemfiles/Gemfile.4.1.lock
CHANGED
data/gemfiles/Gemfile.4.2.1.lock
CHANGED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
module ActiveType
|
|
2
|
+
module Util
|
|
3
|
+
|
|
4
|
+
def cast(object, klass)
|
|
5
|
+
if object.is_a?(ActiveRecord::Relation)
|
|
6
|
+
cast_relation(object, klass)
|
|
7
|
+
elsif object.is_a?(ActiveRecord::Base)
|
|
8
|
+
cast_record(object, klass)
|
|
9
|
+
else
|
|
10
|
+
raise ArgumentError, "Don't know how to cast #{object.inspect}"
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def scoped(klass_or_relation)
|
|
15
|
+
klass_or_relation.where(nil)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
def cast_record(record, klass)
|
|
21
|
+
# record.becomes(klass).dup
|
|
22
|
+
klass.new do |casted|
|
|
23
|
+
# Rails 3.2, 4.2
|
|
24
|
+
casted.instance_variable_set(:@attributes, record.instance_variable_get(:@attributes))
|
|
25
|
+
# Rails 3.2
|
|
26
|
+
record.instance_variable_set(:@attributes_cache, record.instance_variable_get(:@attributes_cache))
|
|
27
|
+
# Rails 4.2
|
|
28
|
+
casted.instance_variable_set(:@changed_attributes, record.instance_variable_get(:@changed_attributes))
|
|
29
|
+
# Rails 3.2, 4.2
|
|
30
|
+
casted.instance_variable_set(:@new_record, record.new_record?)
|
|
31
|
+
# Rails 3.2, 4.2
|
|
32
|
+
casted.instance_variable_set(:@destroyed, record.destroyed?)
|
|
33
|
+
# Rails 3.2, 4.2
|
|
34
|
+
casted.instance_variable_set(:@errors, record.errors)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def cast_relation(relation, klass)
|
|
39
|
+
scoped(klass).merge(scoped(relation))
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
extend self
|
|
43
|
+
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Make Util methods available under the `ActiveType` namespace
|
|
47
|
+
# like `ActiveType.cast(...)`
|
|
48
|
+
extend Util
|
|
49
|
+
end
|
data/lib/active_type/version.rb
CHANGED
data/lib/active_type.rb
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require 'active_type/version'
|
|
4
4
|
require 'active_record'
|
|
5
|
+
require 'active_type/util'
|
|
5
6
|
require 'active_type/record'
|
|
6
7
|
require 'active_type/object'
|
|
7
8
|
|
|
@@ -10,4 +11,4 @@ if ActiveRecord::VERSION::STRING == '4.2.0'
|
|
|
10
11
|
ActiveType is not compatible with ActiveRecord 4.2.0. Please upgrade to 4.2.1
|
|
11
12
|
For details see https://github.com/makandra/active_type/issues/31
|
|
12
13
|
MESSAGE
|
|
13
|
-
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module UtilSpec
|
|
4
|
+
|
|
5
|
+
class BaseRecord < ActiveRecord::Base
|
|
6
|
+
self.table_name = 'records'
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
class ExtendedRecord < ActiveType::Record[BaseRecord]
|
|
10
|
+
|
|
11
|
+
attribute :virtual_string
|
|
12
|
+
after_initialize :set_virtual_string
|
|
13
|
+
|
|
14
|
+
def set_virtual_string
|
|
15
|
+
self.virtual_string = "persisted_string is #{persisted_string}"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
class Parent < ActiveRecord::Base
|
|
21
|
+
self.table_name = 'sti_records'
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
class Child < Parent
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
class ChildSibling < Parent
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
class ExtendedChild < ActiveType::Record[Child]
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
describe ActiveType::Util do
|
|
36
|
+
|
|
37
|
+
describe '.cast' do
|
|
38
|
+
|
|
39
|
+
describe 'for a relation' do
|
|
40
|
+
|
|
41
|
+
it 'casts a scope to a scope of another class' do
|
|
42
|
+
record = UtilSpec::BaseRecord.create!(persisted_string: 'foo')
|
|
43
|
+
base_scope = UtilSpec::BaseRecord.where(persisted_string: 'foo')
|
|
44
|
+
casted_scope = ActiveType::Util.cast(base_scope, UtilSpec::ExtendedRecord)
|
|
45
|
+
casted_scope.build.should be_a(UtilSpec::ExtendedRecord)
|
|
46
|
+
found_record = casted_scope.find(record.id)
|
|
47
|
+
found_record.persisted_string.should == 'foo'
|
|
48
|
+
found_record.should be_a(UtilSpec::ExtendedRecord)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it 'preserves existing scope conditions' do
|
|
52
|
+
match = UtilSpec::BaseRecord.create!(persisted_string: 'foo')
|
|
53
|
+
no_match = UtilSpec::BaseRecord.create!(persisted_string: 'bar')
|
|
54
|
+
base_scope = UtilSpec::BaseRecord.where(persisted_string: 'foo')
|
|
55
|
+
casted_scope = ActiveType::Util.cast(base_scope, UtilSpec::ExtendedRecord)
|
|
56
|
+
casted_match = UtilSpec::ExtendedRecord.find(match.id)
|
|
57
|
+
casted_scope.to_a.should == [casted_match]
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
describe 'for a record type' do
|
|
63
|
+
|
|
64
|
+
it 'casts a base record to an extended record' do
|
|
65
|
+
base_record = UtilSpec::BaseRecord.create!(persisted_string: 'foo')
|
|
66
|
+
extended_record = ActiveType::Util.cast(base_record, UtilSpec::ExtendedRecord)
|
|
67
|
+
extended_record.should be_a(UtilSpec::ExtendedRecord)
|
|
68
|
+
extended_record.should be_persisted
|
|
69
|
+
extended_record.id.should be_present
|
|
70
|
+
extended_record.id.should == base_record.id
|
|
71
|
+
extended_record.persisted_string.should == 'foo'
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
it 'casts an extended record to a base record' do
|
|
75
|
+
extended_record = UtilSpec::ExtendedRecord.create!(persisted_string: 'foo')
|
|
76
|
+
base_record = ActiveType::Util.cast(extended_record, UtilSpec::BaseRecord)
|
|
77
|
+
base_record.should be_a(UtilSpec::BaseRecord)
|
|
78
|
+
base_record.should be_persisted
|
|
79
|
+
base_record.id.should be_present
|
|
80
|
+
base_record.id.should == extended_record.id
|
|
81
|
+
base_record.persisted_string.should == 'foo'
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
it 'calls after_initialize callbacks of the cast target' do
|
|
85
|
+
base_record = UtilSpec::BaseRecord.create!(persisted_string: 'foo')
|
|
86
|
+
extended_record = ActiveType::Util.cast(base_record, UtilSpec::ExtendedRecord)
|
|
87
|
+
extended_record.virtual_string.should be_present
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
it 'lets after_initialize callbacks access attributes (bug in ActiveRecord#becomes)' do
|
|
91
|
+
base_record = UtilSpec::BaseRecord.create!(persisted_string: 'foo')
|
|
92
|
+
extended_record = ActiveType::Util.cast(base_record, UtilSpec::ExtendedRecord)
|
|
93
|
+
extended_record.virtual_string.should == 'persisted_string is foo'
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
it 'preserves the #type of an STI record that is casted to an ExtendedRecord' do
|
|
97
|
+
child_record = UtilSpec::Child.create!(persisted_string: 'foo')
|
|
98
|
+
extended_child_record = ActiveType::Util.cast(child_record, UtilSpec::ExtendedChild)
|
|
99
|
+
extended_child_record.should be_a(UtilSpec::ExtendedChild)
|
|
100
|
+
extended_child_record.type.should == 'UtilSpec::Child'
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
it 'changes the #type of an STI record when casted to another type in the hierarchy' do
|
|
104
|
+
child_record = UtilSpec::Child.create!(persisted_string: 'foo')
|
|
105
|
+
child_sibling_record = ActiveType::Util.cast(child_record, UtilSpec::ChildSibling)
|
|
106
|
+
child_sibling_record.should be_a(UtilSpec::ChildSibling)
|
|
107
|
+
child_sibling_record.type.should == 'UtilSpec::Child'
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
it 'preserves dirty tracking flags' do
|
|
111
|
+
base_record = UtilSpec::BaseRecord.create!(persisted_string: 'foo')
|
|
112
|
+
base_record.changes.should == {}
|
|
113
|
+
base_record.persisted_string = 'bar'
|
|
114
|
+
base_record.changes.should == { 'persisted_string' => ['foo', 'bar'] }
|
|
115
|
+
extended_record = ActiveType::Util.cast(base_record, UtilSpec::ExtendedRecord)
|
|
116
|
+
extended_record.should be_a(UtilSpec::ExtendedRecord)
|
|
117
|
+
extended_record.changes.should == { 'persisted_string' => ['foo', 'bar'] }
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
it "exposes all methods through ActiveType's root namespace" do
|
|
125
|
+
ActiveType.should respond_to(:cast)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: active_type
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Tobias Kraze
|
|
@@ -9,7 +9,7 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date: 2015-06-
|
|
12
|
+
date: 2015-06-12 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: bundler
|
|
@@ -88,6 +88,7 @@ files:
|
|
|
88
88
|
- lib/active_type/object.rb
|
|
89
89
|
- lib/active_type/record.rb
|
|
90
90
|
- lib/active_type/type_caster.rb
|
|
91
|
+
- lib/active_type/util.rb
|
|
91
92
|
- lib/active_type/version.rb
|
|
92
93
|
- lib/active_type/virtual_attributes.rb
|
|
93
94
|
- spec/active_type/extended_record/single_table_inheritance_spec.rb
|
|
@@ -95,6 +96,7 @@ files:
|
|
|
95
96
|
- spec/active_type/nested_attributes_spec.rb
|
|
96
97
|
- spec/active_type/object_spec.rb
|
|
97
98
|
- spec/active_type/record_spec.rb
|
|
99
|
+
- spec/active_type/util_spec.rb
|
|
98
100
|
- spec/integration/holidays_spec.rb
|
|
99
101
|
- spec/integration/shape_spec.rb
|
|
100
102
|
- spec/integration/sign_in_spec.rb
|
|
@@ -142,6 +144,7 @@ test_files:
|
|
|
142
144
|
- spec/active_type/nested_attributes_spec.rb
|
|
143
145
|
- spec/active_type/object_spec.rb
|
|
144
146
|
- spec/active_type/record_spec.rb
|
|
147
|
+
- spec/active_type/util_spec.rb
|
|
145
148
|
- spec/integration/holidays_spec.rb
|
|
146
149
|
- spec/integration/shape_spec.rb
|
|
147
150
|
- spec/integration/sign_in_spec.rb
|