active_type 0.3.5 → 0.4.0

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: 36a9d94011bdc8c1f856f86a6e8727c486a5c913
4
- data.tar.gz: 4519e88999647fdfa0010d316c93a74121e3e713
3
+ metadata.gz: af57ff59af07cfdb0a8576c733da8aa2d0e254ce
4
+ data.tar.gz: e1e04618118baf2b5260e20ed3685d695930e756
5
5
  SHA512:
6
- metadata.gz: 73db269866a0b4cfc512636679733ea14e9c4d5b1130804b305eec33a771dace04ef08a31c91637c9e0a97a79b8b878a8d8be519eceded9a1b43492d49b7bfd9
7
- data.tar.gz: daacc8590bd0afd465eafdb0cca1967c4a8612a34180587d9e20cc65831b39456753ddba149c3e42d2d92708f047f6b2e4d1edf2d7c588ec7c98a0252e2f77a2
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
 
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- active_type (0.3.4)
4
+ active_type (0.4.0)
5
5
  activerecord (>= 3.2)
6
6
 
7
7
  GEM
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- active_type (0.3.4)
4
+ active_type (0.4.0)
5
5
  activerecord (>= 3.2)
6
6
 
7
7
  GEM
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- active_type (0.3.4)
4
+ active_type (0.4.0)
5
5
  activerecord (>= 3.2)
6
6
 
7
7
  GEM
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- active_type (0.3.4)
4
+ active_type (0.4.0)
5
5
  activerecord (>= 3.2)
6
6
 
7
7
  GEM
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- active_type (0.3.4)
4
+ active_type (0.4.0)
5
5
  activerecord (>= 3.2)
6
6
 
7
7
  GEM
@@ -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
@@ -1,3 +1,3 @@
1
1
  module ActiveType
2
- VERSION = '0.3.5'
2
+ VERSION = '0.4.0'
3
3
  end
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.3.5
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-11 00:00:00.000000000 Z
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