active_type 0.5.0 → 0.6.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: 87578ffca30cf6e55491dbdf6d2979e5f1417983
4
- data.tar.gz: 85c59e32dfd6f173cee644da43706f74e1591d6e
3
+ metadata.gz: b973cce18664ad143d834c1ab76a67560a7d7625
4
+ data.tar.gz: 8de998fb74cc5a6bc9217b072461ac293cf83951
5
5
  SHA512:
6
- metadata.gz: 63c1a195fb0f6cb52ec7cdcfcdf7f32bb78dc8d584edde830eb9de59690b02bc67b2500b1365d4e3f534f2900da9bde01d006d9a74b68a205159f96c433c01dd
7
- data.tar.gz: 87f1849abb23e4c2181d3509d6d40d6757f296f011aa8e21d7afb74d6e686b120aa2a76e905ac04a5b126d560200f8e8309188538f160f5053c1f99cdfa6e6fe
6
+ metadata.gz: 28e1d976f66a72868ce6321a589235bb1536accd6b01fb5312f337d76ad191e3542b324e98e1b640e2718a45b8e423bdae5b1512e75fe50bc3896381bcae4f55
7
+ data.tar.gz: 1582cff084f91960662efda6b38ce5fa8d5ff4379e11a5b3181b64f70f1021b5b3074ea33c867a362942ae912ca4bcbba942daf53db1874f6548b3daf6b439e3
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/.travis.yml CHANGED
@@ -1,10 +1,10 @@
1
1
  language: ruby
2
2
  rvm:
3
- - "1.8.7"
4
3
  - "1.9.3"
5
4
  - "2.0.0"
6
5
  - "2.1.7"
7
6
  - "2.2.4"
7
+ - "2.3.1"
8
8
  gemfile:
9
9
  - gemfiles/Gemfile.3.2.mysql2
10
10
  - gemfiles/Gemfile.3.2.sqlite3
@@ -13,6 +13,9 @@ gemfile:
13
13
  - gemfiles/Gemfile.4.2.1.mysql2
14
14
  - gemfiles/Gemfile.4.2.1.pg
15
15
  - gemfiles/Gemfile.4.2.1.sqlite3
16
+ - gemfiles/Gemfile.5.0.0.mysql2
17
+ - gemfiles/Gemfile.5.0.0.pg
18
+ - gemfiles/Gemfile.5.0.0.sqlite3
16
19
  before_script:
17
20
  - psql -c 'create database active_type_test;' -U postgres
18
21
  - mysql -e 'create database IF NOT EXISTS active_type_test;'
@@ -27,16 +30,6 @@ branches:
27
30
  - master
28
31
  matrix:
29
32
  exclude:
30
- - rvm: "1.8.7"
31
- gemfile: gemfiles/Gemfile.4.0.sqlite3
32
- - rvm: "1.8.7"
33
- gemfile: gemfiles/Gemfile.4.1.sqlite3
34
- - rvm: "1.8.7"
35
- gemfile: gemfiles/Gemfile.4.2.1.sqlite3
36
- - rvm: "1.8.7"
37
- gemfile: gemfiles/Gemfile.4.2.1.mysql2
38
- - rvm: "1.8.7"
39
- gemfile: gemfiles/Gemfile.4.2.1.pg
40
33
  - rvm: "1.9.3"
41
34
  gemfile: gemfiles/Gemfile.4.0.sqlite3
42
35
  - rvm: "1.9.3"
@@ -45,6 +38,12 @@ matrix:
45
38
  gemfile: gemfiles/Gemfile.4.2.1.pg
46
39
  - rvm: "1.9.3"
47
40
  gemfile: gemfiles/Gemfile.3.2.mysql2
41
+ - rvm: "1.9.3"
42
+ gemfile: gemfiles/Gemfile.5.0.0.sqlite3
43
+ - rvm: "1.9.3"
44
+ gemfile: gemfiles/Gemfile.5.0.0.mysql2
45
+ - rvm: "1.9.3"
46
+ gemfile: gemfiles/Gemfile.5.0.0.pg
48
47
  - rvm: "2.0.0"
49
48
  gemfile: gemfiles/Gemfile.4.0.sqlite3
50
49
  - rvm: "2.0.0"
@@ -53,6 +52,14 @@ matrix:
53
52
  gemfile: gemfiles/Gemfile.4.2.1.pg
54
53
  - rvm: "2.0.0"
55
54
  gemfile: gemfiles/Gemfile.3.2.mysql2
55
+ - rvm: "2.0.0"
56
+ gemfile: gemfiles/Gemfile.4.1.sqlite3
57
+ - rvm: "2.0.0"
58
+ gemfile: gemfiles/Gemfile.5.0.0.sqlite3
59
+ - rvm: "2.0.0"
60
+ gemfile: gemfiles/Gemfile.5.0.0.mysql2
61
+ - rvm: "2.0.0"
62
+ gemfile: gemfiles/Gemfile.5.0.0.pg
56
63
  - rvm: "2.1.7"
57
64
  gemfile: gemfiles/Gemfile.4.0.sqlite3
58
65
  - rvm: "2.1.7"
@@ -61,3 +68,21 @@ matrix:
61
68
  gemfile: gemfiles/Gemfile.4.2.1.pg
62
69
  - rvm: "2.1.7"
63
70
  gemfile: gemfiles/Gemfile.3.2.mysql2
71
+ - rvm: "2.1.7"
72
+ gemfile: gemfiles/Gemfile.4.1.sqlite3
73
+ - rvm: "2.1.7"
74
+ gemfile: gemfiles/Gemfile.5.0.0.sqlite3
75
+ - rvm: "2.1.7"
76
+ gemfile: gemfiles/Gemfile.5.0.0.mysql2
77
+ - rvm: "2.1.7"
78
+ gemfile: gemfiles/Gemfile.5.0.0.pg
79
+ - rvm: "2.2.4"
80
+ gemfile: gemfiles/Gemfile.4.0.sqlite3
81
+ - rvm: "2.2.4"
82
+ gemfile: gemfiles/Gemfile.4.2.1.mysql2
83
+ - rvm: "2.2.4"
84
+ gemfile: gemfiles/Gemfile.4.2.1.pg
85
+ - rvm: "2.2.4"
86
+ gemfile: gemfiles/Gemfile.3.2.mysql2
87
+ - rvm: "2.2.4"
88
+ gemfile: gemfiles/Gemfile.4.1.sqlite3
data/CHANGELOG.md CHANGED
@@ -4,9 +4,38 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  ActiveType is in a pre-1.0 state. This means that its APIs and behavior are subject to breaking changes without deprecation notices. Until 1.0, version numbers will follow a [Semver][]-ish `0.y.z` format, where `y` is incremented when new features or breaking changes are introduced, and `z` is incremented for lesser changes or bug fixes.
6
6
 
7
- ## [Unreleased]
7
+ ## [0.6.0][] (2016-07-05)
8
8
 
9
- * Your contribution here!
9
+ * Drop support for 1.8.7.
10
+ * Rails 5 compatibility.
11
+
12
+ ## [0.5.1][] (2016-05-09)
13
+
14
+ * Fix an issue with incorrectly copied errors on Util.cast.
15
+
16
+ ## [0.5.0][] (2016-04-08)
17
+
18
+ * Nicer `#inspect` method.
19
+
20
+ ## [0.4.5][] (2016-02-01)
21
+
22
+ * Fixed issue `#dup`ing `ActiveType::Object`
23
+
24
+ ## [0.4.4][] (2016-01-18)
25
+
26
+ * Call `#after_commit` for `ActiveType::Object`
27
+
28
+ ## [0.4.3][] (2015-11-11)
29
+
30
+ * Fix issue with Booleans on mysql.
31
+
32
+ ## [0.4.2][] (2015-09-24)
33
+
34
+ * Add `attribute_will_change!` for virtual attributes.
35
+
36
+ ## [0.4.1][] (2015-09-24)
37
+
38
+ * Add `attribute_was` for virtual attributes.
10
39
 
11
40
  ## [0.4.0][] (2015-06-12)
12
41
 
data/README.md CHANGED
@@ -50,6 +50,23 @@ class SignUp < ActiveType::Record[User]
50
50
  end
51
51
  ```
52
52
 
53
+
54
+ ### A note on Rails 5
55
+
56
+ Rails 5 comes with its own implementation of `.attribute`. This implementation is functionally very
57
+ similar, but not identical to ActiveType's.
58
+
59
+ We have decided to continue to use our own implementation. This means that if you use ActiveType, `ActiveRecord::Base.attribute` will be overriden.
60
+
61
+ The following behaviours are different than in vanilla Rails 5:
62
+
63
+ - Defaults `proc`s are evaluated in instance context, not class context.
64
+ - Defaults are evaluated lazily.
65
+ - You can override attributes with custom methods and use `super`.
66
+ - Attributes will work on records retrieved via `.find`.
67
+ - Attributes will be duped if you dup the record.
68
+
69
+
53
70
  ### ActiveType::Object
54
71
 
55
72
 
@@ -307,14 +324,14 @@ sign_up.is_a?(SignUp) # => true
307
324
  Supported Rails versions
308
325
  ------------------------
309
326
 
310
- ActiveType is tested against ActiveRecord 3.2, 4.0, 4.1 and 4.2.
327
+ ActiveType is tested against ActiveRecord 3.2, 4.0, 4.1, 4.2 and 5.0.
311
328
 
312
329
  Later versions might work, earlier will not.
313
330
 
314
331
  Supported Ruby versions
315
332
  ------------------------
316
333
 
317
- ActiveType is tested against MRI 1.8.7 (for 3.2 only), 1.9.3, 2.0.0, 2.1.2.
334
+ ActiveType is tested against 1.9.3, 2.0.0, 2.1.2 (for 4.x only), 2.2.4 and 2.3.1.
318
335
 
319
336
 
320
337
  Installation
data/active_type.gemspec CHANGED
@@ -21,4 +21,5 @@ Gem::Specification.new do |s|
21
21
 
22
22
  s.add_runtime_dependency('activerecord', '>= 3.2')
23
23
 
24
+ s.required_ruby_version = '>= 1.9.3'
24
25
  end
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- active_type (0.5.0)
4
+ active_type (0.6.0)
5
5
  activerecord (>= 3.2)
6
6
 
7
7
  GEM
@@ -50,4 +50,4 @@ DEPENDENCIES
50
50
  rspec (~> 3.4)
51
51
 
52
52
  BUNDLED WITH
53
- 1.11.2
53
+ 1.12.1
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- active_type (0.5.0)
4
+ active_type (0.6.0)
5
5
  activerecord (>= 3.2)
6
6
 
7
7
  GEM
@@ -50,4 +50,4 @@ DEPENDENCIES
50
50
  sqlite3
51
51
 
52
52
  BUNDLED WITH
53
- 1.11.2
53
+ 1.12.1
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- active_type (0.5.0)
4
+ active_type (0.6.0)
5
5
  activerecord (>= 3.2)
6
6
 
7
7
  GEM
@@ -55,4 +55,4 @@ DEPENDENCIES
55
55
  sqlite3
56
56
 
57
57
  BUNDLED WITH
58
- 1.11.2
58
+ 1.12.1
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- active_type (0.5.0)
4
+ active_type (0.6.0)
5
5
  activerecord (>= 3.2)
6
6
 
7
7
  GEM
@@ -54,4 +54,4 @@ DEPENDENCIES
54
54
  sqlite3
55
55
 
56
56
  BUNDLED WITH
57
- 1.11.2
57
+ 1.12.1
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- active_type (0.5.0)
4
+ active_type (0.6.0)
5
5
  activerecord (>= 3.2)
6
6
 
7
7
  GEM
@@ -54,4 +54,4 @@ DEPENDENCIES
54
54
  rspec (~> 3.4)
55
55
 
56
56
  BUNDLED WITH
57
- 1.11.2
57
+ 1.12.1
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- active_type (0.5.0)
4
+ active_type (0.6.0)
5
5
  activerecord (>= 3.2)
6
6
 
7
7
  GEM
@@ -54,4 +54,4 @@ DEPENDENCIES
54
54
  rspec (~> 3.4)
55
55
 
56
56
  BUNDLED WITH
57
- 1.11.2
57
+ 1.12.1
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- active_type (0.5.0)
4
+ active_type (0.6.0)
5
5
  activerecord (>= 3.2)
6
6
 
7
7
  GEM
@@ -54,4 +54,4 @@ DEPENDENCIES
54
54
  sqlite3
55
55
 
56
56
  BUNDLED WITH
57
- 1.11.2
57
+ 1.12.1
@@ -0,0 +1,7 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'activerecord', '~>5.0.0'
4
+ gem 'rspec', '~>3.4'
5
+ gem 'mysql2', '~> 0.3.17'
6
+
7
+ gem 'active_type', :path => '..'
@@ -0,0 +1,54 @@
1
+ PATH
2
+ remote: ..
3
+ specs:
4
+ active_type (0.6.0)
5
+ activerecord (>= 3.2)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ activemodel (5.0.0)
11
+ activesupport (= 5.0.0)
12
+ activerecord (5.0.0)
13
+ activemodel (= 5.0.0)
14
+ activesupport (= 5.0.0)
15
+ arel (~> 7.0)
16
+ activesupport (5.0.0)
17
+ concurrent-ruby (~> 1.0, >= 1.0.2)
18
+ i18n (~> 0.7)
19
+ minitest (~> 5.1)
20
+ tzinfo (~> 1.1)
21
+ arel (7.0.0)
22
+ concurrent-ruby (1.0.2)
23
+ diff-lcs (1.2.5)
24
+ i18n (0.7.0)
25
+ minitest (5.9.0)
26
+ mysql2 (0.3.21)
27
+ rspec (3.5.0)
28
+ rspec-core (~> 3.5.0)
29
+ rspec-expectations (~> 3.5.0)
30
+ rspec-mocks (~> 3.5.0)
31
+ rspec-core (3.5.0)
32
+ rspec-support (~> 3.5.0)
33
+ rspec-expectations (3.5.0)
34
+ diff-lcs (>= 1.2.0, < 2.0)
35
+ rspec-support (~> 3.5.0)
36
+ rspec-mocks (3.5.0)
37
+ diff-lcs (>= 1.2.0, < 2.0)
38
+ rspec-support (~> 3.5.0)
39
+ rspec-support (3.5.0)
40
+ thread_safe (0.3.5)
41
+ tzinfo (1.2.2)
42
+ thread_safe (~> 0.1)
43
+
44
+ PLATFORMS
45
+ ruby
46
+
47
+ DEPENDENCIES
48
+ active_type!
49
+ activerecord (~> 5.0.0)
50
+ mysql2 (~> 0.3.17)
51
+ rspec (~> 3.4)
52
+
53
+ BUNDLED WITH
54
+ 1.12.1
@@ -0,0 +1,7 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'activerecord', '~>5.0.0'
4
+ gem 'rspec', '~>3.4'
5
+ gem 'pg'
6
+
7
+ gem 'active_type', :path => '..'
@@ -0,0 +1,54 @@
1
+ PATH
2
+ remote: ..
3
+ specs:
4
+ active_type (0.6.0)
5
+ activerecord (>= 3.2)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ activemodel (5.0.0)
11
+ activesupport (= 5.0.0)
12
+ activerecord (5.0.0)
13
+ activemodel (= 5.0.0)
14
+ activesupport (= 5.0.0)
15
+ arel (~> 7.0)
16
+ activesupport (5.0.0)
17
+ concurrent-ruby (~> 1.0, >= 1.0.2)
18
+ i18n (~> 0.7)
19
+ minitest (~> 5.1)
20
+ tzinfo (~> 1.1)
21
+ arel (7.0.0)
22
+ concurrent-ruby (1.0.2)
23
+ diff-lcs (1.2.5)
24
+ i18n (0.7.0)
25
+ minitest (5.9.0)
26
+ pg (0.18.4)
27
+ rspec (3.5.0)
28
+ rspec-core (~> 3.5.0)
29
+ rspec-expectations (~> 3.5.0)
30
+ rspec-mocks (~> 3.5.0)
31
+ rspec-core (3.5.0)
32
+ rspec-support (~> 3.5.0)
33
+ rspec-expectations (3.5.0)
34
+ diff-lcs (>= 1.2.0, < 2.0)
35
+ rspec-support (~> 3.5.0)
36
+ rspec-mocks (3.5.0)
37
+ diff-lcs (>= 1.2.0, < 2.0)
38
+ rspec-support (~> 3.5.0)
39
+ rspec-support (3.5.0)
40
+ thread_safe (0.3.5)
41
+ tzinfo (1.2.2)
42
+ thread_safe (~> 0.1)
43
+
44
+ PLATFORMS
45
+ ruby
46
+
47
+ DEPENDENCIES
48
+ active_type!
49
+ activerecord (~> 5.0.0)
50
+ pg
51
+ rspec (~> 3.4)
52
+
53
+ BUNDLED WITH
54
+ 1.12.1
@@ -0,0 +1,7 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'activerecord', '~>5.0.0'
4
+ gem 'rspec', '~> 3.4'
5
+ gem 'sqlite3'
6
+
7
+ gem 'active_type', :path => '..'
@@ -0,0 +1,54 @@
1
+ PATH
2
+ remote: ..
3
+ specs:
4
+ active_type (0.6.0)
5
+ activerecord (>= 3.2)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ activemodel (5.0.0)
11
+ activesupport (= 5.0.0)
12
+ activerecord (5.0.0)
13
+ activemodel (= 5.0.0)
14
+ activesupport (= 5.0.0)
15
+ arel (~> 7.0)
16
+ activesupport (5.0.0)
17
+ concurrent-ruby (~> 1.0, >= 1.0.2)
18
+ i18n (~> 0.7)
19
+ minitest (~> 5.1)
20
+ tzinfo (~> 1.1)
21
+ arel (7.0.0)
22
+ concurrent-ruby (1.0.2)
23
+ diff-lcs (1.2.5)
24
+ i18n (0.7.0)
25
+ minitest (5.9.0)
26
+ rspec (3.5.0)
27
+ rspec-core (~> 3.5.0)
28
+ rspec-expectations (~> 3.5.0)
29
+ rspec-mocks (~> 3.5.0)
30
+ rspec-core (3.5.0)
31
+ rspec-support (~> 3.5.0)
32
+ rspec-expectations (3.5.0)
33
+ diff-lcs (>= 1.2.0, < 2.0)
34
+ rspec-support (~> 3.5.0)
35
+ rspec-mocks (3.5.0)
36
+ diff-lcs (>= 1.2.0, < 2.0)
37
+ rspec-support (~> 3.5.0)
38
+ rspec-support (3.5.0)
39
+ sqlite3 (1.3.11)
40
+ thread_safe (0.3.5)
41
+ tzinfo (1.2.2)
42
+ thread_safe (~> 0.1)
43
+
44
+ PLATFORMS
45
+ ruby
46
+
47
+ DEPENDENCIES
48
+ active_type!
49
+ activerecord (~> 5.0.0)
50
+ rspec (~> 3.4)
51
+ sqlite3
52
+
53
+ BUNDLED WITH
54
+ 1.12.1
@@ -23,13 +23,48 @@ module ActiveType
23
23
 
24
24
  private
25
25
 
26
- def find_sti_class(type_name)
27
- sti_class = super
28
- if self <= sti_class
29
- self
30
- else
31
- sti_class
26
+ if ActiveRecord::VERSION::MAJOR < 5
27
+
28
+ def find_sti_class(type_name)
29
+ sti_class = super
30
+ if self <= sti_class
31
+ self
32
+ else
33
+ sti_class
34
+ end
32
35
  end
36
+
37
+ else
38
+
39
+ # Rails 5 find_sti_class does a sanity check for proper inheritance that fails for
40
+ # our usecase
41
+ # copied from activerecord/lib/active_record/inheritance.rb
42
+ def find_sti_class(type_name)
43
+ type_name = base_class.type_for_attribute(inheritance_column).cast(type_name)
44
+ subclass = begin
45
+ if store_full_sti_class
46
+ ActiveSupport::Dependencies.constantize(type_name)
47
+ else
48
+ compute_type(type_name)
49
+ end
50
+ rescue NameError
51
+ raise ActiveRecord::SubclassNotFound,
52
+ "The single-table inheritance mechanism failed to locate the subclass: '#{type_name}'. " \
53
+ "This error is raised because the column '#{inheritance_column}' is reserved for storing the class in case of inheritance. " \
54
+ "Please rename this column if you didn't intend it to be used for storing the inheritance class " \
55
+ "or overwrite #{name}.inheritance_column to use another column for that information."
56
+ end
57
+ #### our code starts here
58
+ if self <= subclass
59
+ subclass = self
60
+ end
61
+ #### our code ends here
62
+ unless subclass == self || descendants.include?(subclass)
63
+ raise ActiveRecord::SubclassNotFound, "Invalid single-table inheritance type: #{subclass.name} is not a subclass of #{name}"
64
+ end
65
+ subclass
66
+ end
67
+
33
68
  end
34
69
 
35
70
  end
@@ -28,7 +28,7 @@ module ActiveType
28
28
  end
29
29
 
30
30
  def add_attribute(name, options)
31
- @owner.attribute(name, options)
31
+ @owner.attribute(name, :object, options)
32
32
  end
33
33
 
34
34
  def add_writer_method(name, association)
@@ -41,7 +41,7 @@ module ActiveType
41
41
  end
42
42
 
43
43
  def add_autosave(name, association)
44
- save_method = "save_associated_records_for_#{name}"
44
+ save_method = :"save_associated_records_for_#{name}"
45
45
  @module.module_eval do
46
46
  define_method save_method do
47
47
  association.save(self)
@@ -51,7 +51,7 @@ module ActiveType
51
51
  end
52
52
 
53
53
  def add_validation(name, association)
54
- validate_method = "validate_associated_records_for_#{name}"
54
+ validate_method = :"validate_associated_records_for_#{name}"
55
55
  @module.module_eval do
56
56
  define_method validate_method do
57
57
  association.validate(self)
@@ -1,81 +1,167 @@
1
1
  module ActiveType
2
2
 
3
- module NoTable
3
+ if ActiveRecord::VERSION::MAJOR < 5
4
4
 
5
- extend ActiveSupport::Concern
5
+ module NoTable
6
6
 
7
+ extend ActiveSupport::Concern
7
8
 
8
- module ClassMethods
9
+ module ClassMethods
10
+
11
+ def column_types
12
+ {}
13
+ end
14
+
15
+ def columns
16
+ []
17
+ end
18
+
19
+ def primary_key
20
+ nil
21
+ end
22
+
23
+ def destroy(*)
24
+ new
25
+ end
26
+
27
+ def destroy_all(*)
28
+ []
29
+ end
30
+
31
+ def find_by_sql(*)
32
+ []
33
+ end
9
34
 
10
- def primary_key
11
- nil
12
35
  end
13
36
 
14
- def column_types
15
- {}
37
+ def id
38
+ nil
16
39
  end
17
40
 
18
- def columns
41
+ def attribute_names
19
42
  []
20
43
  end
21
44
 
22
- def destroy(*)
23
- new
45
+ def transaction(&block)
46
+ @_current_transaction_records ||= []
47
+ yield
24
48
  end
25
49
 
26
- def destroy_all(*)
27
- []
50
+ def destroy
51
+ @destroyed = true
52
+ freeze
28
53
  end
29
54
 
55
+ def reload
56
+ self
57
+ end
30
58
 
31
- def find_by_sql(*)
32
- []
59
+
60
+ private
61
+
62
+ def create(*)
63
+ true
33
64
  end
34
65
 
35
- end
66
+ def update(*)
67
+ true
68
+ end
36
69
 
37
- def id
38
- nil
39
- end
70
+ if ActiveRecord::Base.private_method_defined?(:create_record)
71
+ def create_record(*)
72
+ true
73
+ end
74
+
75
+ def update_record(*)
76
+ true
77
+ end
78
+ else
79
+ def _create_record(*)
80
+ @new_record = false
81
+ true
82
+ end
83
+
84
+ def _update_record(*)
85
+ true
86
+ end
87
+ end
40
88
 
41
- def attribute_names
42
- []
43
89
  end
44
90
 
45
- def transaction(&block)
46
- @_current_transaction_records ||= []
47
- yield
48
- end
91
+ else
49
92
 
50
- def destroy
51
- @destroyed = true
52
- freeze
53
- end
93
+ # Rails 5+
54
94
 
55
- def reload
56
- self
57
- end
95
+ module NoTable
58
96
 
97
+ extend ActiveSupport::Concern
59
98
 
60
- private
99
+ class DummySchemaCache
61
100
 
62
- def create(*)
63
- true
64
- end
101
+ def columns_hash(table_name)
102
+ {}
103
+ end
65
104
 
66
- def update(*)
67
- true
68
- end
105
+ def data_source_exists?(table_name)
106
+ false
107
+ end
69
108
 
70
- if ActiveRecord::Base.private_method_defined?(:create_record)
71
- def create_record(*)
109
+ def clear_data_source_cache!(table_name)
110
+ end
111
+
112
+ end
113
+
114
+ class DummyConnection < ActiveRecord::ConnectionAdapters::AbstractAdapter
115
+
116
+ attr_reader :schema_cache
117
+
118
+ def initialize(*)
119
+ super
120
+ @schema_cache = DummySchemaCache.new
121
+ end
122
+
123
+ end
124
+
125
+ module ClassMethods
126
+
127
+ def connection
128
+ @connection ||= DummyConnection.new(nil)
129
+ end
130
+
131
+ def destroy(*)
132
+ new
133
+ end
134
+
135
+ def destroy_all(*)
136
+ []
137
+ end
138
+
139
+ def find_by_sql(*)
140
+ []
141
+ end
142
+
143
+ end
144
+
145
+ def destroy
146
+ @destroyed = true
147
+ freeze
148
+ end
149
+
150
+ def reload
151
+ self
152
+ end
153
+
154
+
155
+ private
156
+
157
+ def create(*)
72
158
  true
73
159
  end
74
160
 
75
- def update_record(*)
161
+ def update(*)
76
162
  true
77
163
  end
78
- else
164
+
79
165
  def _create_record(*)
80
166
  @new_record = false
81
167
  true
@@ -84,6 +170,7 @@ module ActiveType
84
170
  def _update_record(*)
85
171
  true
86
172
  end
173
+
87
174
  end
88
175
 
89
176
  end
@@ -4,8 +4,10 @@ module ActiveType
4
4
  def self.get(type, connection)
5
5
  native_caster = if ActiveRecord::VERSION::STRING < '4.2'
6
6
  NativeCasters::DelegateToColumn.new(type)
7
+ elsif ActiveRecord::VERSION::STRING < '5'
8
+ NativeCasters::DelegateToRails4Type.new(type, connection)
7
9
  else
8
- NativeCasters::DelegateToType.new(type, connection)
10
+ NativeCasters::DelegateToRails5Type.new(type)
9
11
  end
10
12
  new(type, native_caster)
11
13
  end
@@ -62,7 +64,7 @@ module ActiveType
62
64
 
63
65
  # Adapter for Rails 4.2+.
64
66
  # In these versions, casting logic lives in subclasses of ActiveRecord::Type::Value
65
- class DelegateToType
67
+ class DelegateToRails4Type
66
68
 
67
69
  def initialize(type, connection)
68
70
  # The specified type (e.g. "string") may not necessary match the
@@ -87,6 +89,32 @@ module ActiveType
87
89
 
88
90
  end
89
91
 
92
+ # Adapter for Rails 5+.
93
+ # In these versions, casting logic lives in subclasses of ActiveRecord::Type::Value
94
+ class DelegateToRails5Type
95
+
96
+ def initialize(type)
97
+ @active_record_type = lookup(type)
98
+ end
99
+
100
+ def type_cast_from_user(value)
101
+ @active_record_type.cast(value)
102
+ end
103
+
104
+ private
105
+
106
+ def lookup(type)
107
+ if type.respond_to?(:cast)
108
+ type
109
+ else
110
+ ActiveRecord::Type.lookup(type)
111
+ end
112
+ rescue ::ArgumentError => e
113
+ ActiveRecord::Type::Value.new
114
+ end
115
+
116
+ end
117
+
90
118
  end
91
119
 
92
120
  end
@@ -23,15 +23,24 @@ module ActiveType
23
23
  # Rails 3.2, 4.2
24
24
  casted.instance_variable_set(:@attributes, record.instance_variable_get(:@attributes))
25
25
  # Rails 3.2
26
- record.instance_variable_set(:@attributes_cache, record.instance_variable_get(:@attributes_cache))
26
+ casted.instance_variable_set(:@attributes_cache, record.instance_variable_get(:@attributes_cache))
27
27
  # Rails 4.2
28
28
  casted.instance_variable_set(:@changed_attributes, record.instance_variable_get(:@changed_attributes))
29
+ # Rails 5.0
30
+ casted.instance_variable_set(:@mutation_tracker, record.instance_variable_get(:@mutation_tracker))
29
31
  # Rails 3.2, 4.2
30
32
  casted.instance_variable_set(:@new_record, record.new_record?)
31
33
  # Rails 3.2, 4.2
32
34
  casted.instance_variable_set(:@destroyed, record.destroyed?)
33
35
  # Rails 3.2, 4.2
34
- casted.instance_variable_set(:@errors, record.errors)
36
+ errors = record.errors
37
+ if errors.kind_of? ActiveModel::Errors
38
+ errors = errors.dup
39
+ # otherwise attributes defined in ActiveType::Record
40
+ # won't be visible to `errors.add`
41
+ errors.instance_variable_set(:@base, casted)
42
+ end
43
+ casted.instance_variable_set(:@errors, errors)
35
44
  end
36
45
  end
37
46
 
@@ -1,3 +1,3 @@
1
1
  module ActiveType
2
- VERSION = '0.5.0'
2
+ VERSION = '0.6.0'
3
3
  end
@@ -13,7 +13,11 @@ module NestedAttributesSpec
13
13
 
14
14
  def check_fail
15
15
  if fail_on_save == true
16
- false
16
+ if ActiveRecord::VERSION::MAJOR >= 5
17
+ throw :abort
18
+ else
19
+ false
20
+ end
17
21
  end
18
22
  end
19
23
 
@@ -3,6 +3,12 @@ require 'ostruct'
3
3
 
4
4
  module ObjectSpec
5
5
 
6
+ def self.type
7
+ if ActiveRecord::VERSION::MAJOR >= 5
8
+ @type ||= ActiveModel::Type::Value.new
9
+ end
10
+ end
11
+
6
12
  class Object < ActiveType::Object
7
13
 
8
14
  attribute :virtual_string, :string
@@ -11,6 +17,7 @@ module ObjectSpec
11
17
  attribute :virtual_date, :date
12
18
  attribute :virtual_boolean, :boolean
13
19
  attribute :virtual_attribute
20
+ attribute :virtual_type_attribute, ObjectSpec.type
14
21
 
15
22
  end
16
23
 
@@ -171,6 +178,10 @@ describe ActiveType::Object do
171
178
  describe 'untyped columns' do
172
179
  it_should_behave_like 'an untyped column', :virtual_attribute
173
180
  end
181
+
182
+ describe 'type columns' do
183
+ it_should_behave_like 'a coercible type column', :virtual_type_attribute, ObjectSpec.type
184
+ end
174
185
  end
175
186
 
176
187
  describe 'query methods' do
@@ -218,7 +229,7 @@ describe ActiveType::Object do
218
229
  subject.virtual_boolean = true
219
230
  subject.virtual_attribute = OpenStruct.new({:test => "openstruct"})
220
231
 
221
- expect(subject.inspect).to eq("#<ObjectSpec::Object virtual_attribute: #<OpenStruct test=\"openstruct\">, virtual_boolean: true, virtual_date: \"#{Date.today}\", virtual_integer: 17, virtual_string: \"string\", virtual_time: \"#{t.to_s(:db)}\">")
232
+ expect(subject.inspect).to eq("#<ObjectSpec::Object virtual_attribute: #<OpenStruct test=\"openstruct\">, virtual_boolean: true, virtual_date: \"#{Date.today}\", virtual_integer: 17, virtual_string: \"string\", virtual_time: \"#{t.to_s(:db)}\", virtual_type_attribute: nil>")
222
233
  end
223
234
 
224
235
  end
@@ -236,6 +247,7 @@ describe ActiveType::Object do
236
247
  "virtual_date" => nil,
237
248
  "virtual_boolean" => nil,
238
249
  "virtual_attribute" => nil,
250
+ "virtual_type_attribute" => nil,
239
251
  })
240
252
  end
241
253
 
@@ -252,6 +264,7 @@ describe ActiveType::Object do
252
264
  "virtual_boolean" => nil,
253
265
  "virtual_attribute" => nil,
254
266
  "another_virtual_string" => nil,
267
+ "virtual_type_attribute" => nil,
255
268
  })
256
269
  end
257
270
 
@@ -268,6 +281,7 @@ describe ActiveType::Object do
268
281
  "virtual_boolean" => nil,
269
282
  "virtual_attribute" => nil,
270
283
  "another_virtual_string" => nil,
284
+ "virtual_type_attribute" => nil,
271
285
  })
272
286
  end
273
287
 
@@ -381,7 +395,13 @@ describe ActiveType::Object do
381
395
  %w[before_validation before_save].each do |callback|
382
396
 
383
397
  it "aborts the chain when #{callback} returns false" do
384
- allow(subject).to receive_messages("#{callback}_callback" => false)
398
+ if ActiveRecord::VERSION::MAJOR >= 5
399
+ allow(subject).to receive("#{callback}_callback") do
400
+ throw(:abort)
401
+ end
402
+ else
403
+ allow(subject).to receive_messages("#{callback}_callback" => false)
404
+ end
385
405
 
386
406
  expect(subject.save).to be_falsey
387
407
  end
@@ -404,9 +424,17 @@ describe ActiveType::Object do
404
424
 
405
425
  end
406
426
 
427
+ describe '#id' do
428
+
429
+ it 'is nil' do
430
+ expect(subject.id).to eq nil
431
+ end
432
+
433
+ end
434
+
407
435
  describe '.find' do
408
436
  it 'raises an error' do
409
- error = if ActiveRecord::VERSION::MAJOR >= 4 && ActiveRecord::VERSION::MINOR >= 1
437
+ error = if ActiveRecord::VERSION::MAJOR == 4 && ActiveRecord::VERSION::MINOR >= 1
410
438
  ActiveRecord::UnknownPrimaryKey
411
439
  else
412
440
  ActiveRecord::RecordNotFound
@@ -3,6 +3,12 @@ require 'ostruct'
3
3
 
4
4
  module RecordSpec
5
5
 
6
+ def self.type
7
+ if ActiveRecord::VERSION::MAJOR >= 5
8
+ @type ||= ActiveModel::Type::Value.new
9
+ end
10
+ end
11
+
6
12
  class Record < ActiveType::Record
7
13
 
8
14
  attribute :virtual_string, :string
@@ -11,6 +17,7 @@ module RecordSpec
11
17
  attribute :virtual_date, :date
12
18
  attribute :virtual_boolean, :boolean
13
19
  attribute :virtual_attribute
20
+ attribute :virtual_type_attribute, RecordSpec.type
14
21
 
15
22
  end
16
23
 
@@ -58,6 +65,7 @@ end
58
65
  describe ActiveType::Record do
59
66
 
60
67
  subject { RecordSpec::Record.new }
68
+ t = Time.new(2016, 2, 1, 12)
61
69
 
62
70
  it 'is a ActiveRecord::Base' do
63
71
  expect(subject).to be_a(ActiveRecord::Base)
@@ -70,22 +78,22 @@ describe ActiveType::Record do
70
78
  describe 'constructors' do
71
79
  subject { RecordSpec::Record }
72
80
 
73
- it_should_behave_like 'ActiveRecord-like constructors', { :persisted_string => "string", :persisted_integer => 100, :persisted_time => Time.now, :persisted_date => Date.today, :persisted_boolean => true }
81
+ it_should_behave_like 'ActiveRecord-like constructors', { :persisted_string => "string", :persisted_integer => 100, :persisted_time => t, :persisted_date => Date.today, :persisted_boolean => true }
74
82
 
75
- it_should_behave_like 'ActiveRecord-like constructors', { :virtual_string => "string", :virtual_integer => 100, :virtual_time => Time.now, :virtual_date => Date.today, :virtual_boolean => true }
83
+ it_should_behave_like 'ActiveRecord-like constructors', { :virtual_string => "string", :virtual_integer => 100, :virtual_time => t, :virtual_date => Date.today, :virtual_boolean => true }
76
84
 
77
85
  end
78
86
 
79
87
  describe 'mass assignment' do
80
- it_should_behave_like 'ActiveRecord-like mass assignment', { :persisted_string => "string", :persisted_integer => 100, :persisted_time => Time.now, :persisted_date => Date.today, :persisted_boolean => true }
88
+ it_should_behave_like 'ActiveRecord-like mass assignment', { :persisted_string => "string", :persisted_integer => 100, :persisted_time => t, :persisted_date => Date.today, :persisted_boolean => true }
81
89
 
82
- it_should_behave_like 'ActiveRecord-like mass assignment', { :virtual_string => "string", :virtual_integer => 100, :virtual_time => Time.now, :virtual_date => Date.today, :virtual_boolean => true }
90
+ it_should_behave_like 'ActiveRecord-like mass assignment', { :virtual_string => "string", :virtual_integer => 100, :virtual_time => t, :virtual_date => Date.today, :virtual_boolean => true }
83
91
  end
84
92
 
85
93
  describe 'accessors' do
86
- it_should_behave_like 'ActiveRecord-like accessors', { :persisted_string => "string", :persisted_integer => 100, :persisted_time => Time.now, :persisted_date => Date.today, :persisted_boolean => true }
94
+ it_should_behave_like 'ActiveRecord-like accessors', { :persisted_string => "string", :persisted_integer => 100, :persisted_time => t, :persisted_date => Date.today, :persisted_boolean => true }
87
95
 
88
- it_should_behave_like 'ActiveRecord-like accessors', { :virtual_string => "string", :virtual_integer => 100, :virtual_time => Time.now, :virtual_date => Date.today, :virtual_boolean => true }
96
+ it_should_behave_like 'ActiveRecord-like accessors', { :virtual_string => "string", :virtual_integer => 100, :virtual_time => t, :virtual_date => Date.today, :virtual_boolean => true }
89
97
  end
90
98
 
91
99
  describe 'overridable attributes' do
@@ -150,6 +158,10 @@ describe ActiveType::Record do
150
158
  describe 'untyped columns' do
151
159
  it_should_behave_like 'an untyped column', :virtual_attribute
152
160
  end
161
+
162
+ describe 'type columns' do
163
+ it_should_behave_like 'a coercible type column', :virtual_type_attribute, RecordSpec.type
164
+ end
153
165
  end
154
166
 
155
167
  describe '#inspect' do
@@ -165,7 +177,7 @@ describe ActiveType::Record do
165
177
  subject.virtual_boolean = true
166
178
  subject.virtual_attribute = OpenStruct.new({:test => "openstruct"})
167
179
 
168
- expect(subject.inspect).to eq("#<RecordSpec::Record id: nil, persisted_boolean: nil, persisted_date: nil, persisted_integer: 20, persisted_string: \"persisted string\", persisted_time: nil, virtual_attribute: #<OpenStruct test=\"openstruct\">, virtual_boolean: true, virtual_date: \"#{Date.today}\", virtual_integer: 17, virtual_string: \"string\", virtual_time: \"#{t.to_s(:db)}\">")
180
+ expect(subject.inspect).to eq("#<RecordSpec::Record id: nil, persisted_boolean: nil, persisted_date: nil, persisted_integer: 20, persisted_string: \"persisted string\", persisted_time: nil, virtual_attribute: #<OpenStruct test=\"openstruct\">, virtual_boolean: true, virtual_date: \"#{Date.today}\", virtual_integer: 17, virtual_string: \"string\", virtual_time: \"#{t.to_s(:db)}\", virtual_type_attribute: nil>")
169
181
  end
170
182
 
171
183
  end
@@ -184,12 +196,13 @@ describe ActiveType::Record do
184
196
  "virtual_date" => nil,
185
197
  "virtual_boolean" => nil,
186
198
  "virtual_attribute" => nil,
199
+ "virtual_type_attribute" => nil,
187
200
  "id" => nil,
188
201
  "persisted_string" => "string",
189
202
  "persisted_integer" => nil,
190
203
  "persisted_time" => nil,
191
204
  "persisted_date" => nil,
192
- "persisted_boolean" => nil
205
+ "persisted_boolean" => nil,
193
206
  })
194
207
  end
195
208
 
@@ -252,4 +265,10 @@ describe ActiveType::Record do
252
265
  it_should_behave_like 'a belongs_to association', :child, RecordSpec::Child
253
266
  end
254
267
 
268
+ it 'can access virtual attributes after .find' do
269
+ subject.save!
270
+ expect(subject.class.find(subject.id).virtual_string).to eq(nil)
271
+ expect(subject.class.find(subject.id).virtual_string).to eq(nil)
272
+ end
273
+
255
274
  end
@@ -9,9 +9,12 @@ module UtilSpec
9
9
  class ExtendedRecord < ActiveType::Record[BaseRecord]
10
10
 
11
11
  attribute :virtual_string
12
+ attribute :virtual_string_for_validation
12
13
  after_initialize :set_virtual_string
14
+ attr_reader :after_initialize_called
13
15
 
14
16
  def set_virtual_string
17
+ @after_initialize_called = true
15
18
  self.virtual_string = "persisted_string is #{persisted_string}"
16
19
  end
17
20
 
@@ -84,7 +87,7 @@ describe ActiveType::Util do
84
87
  it 'calls after_initialize callbacks of the cast target' do
85
88
  base_record = UtilSpec::BaseRecord.create!(:persisted_string => 'foo')
86
89
  extended_record = ActiveType::Util.cast(base_record, UtilSpec::ExtendedRecord)
87
- expect(extended_record.virtual_string).to be_present
90
+ expect(extended_record.after_initialize_called).to eq true
88
91
  end
89
92
 
90
93
  it 'lets after_initialize callbacks access attributes (bug in ActiveRecord#becomes)' do
@@ -117,6 +120,17 @@ describe ActiveType::Util do
117
120
  expect(extended_record.changes).to eq({ 'persisted_string' => ['foo', 'bar'] })
118
121
  end
119
122
 
123
+ it 'associates the error object correctly with the new type (BUGFIX)' do
124
+ base_record = UtilSpec::BaseRecord.create!(:persisted_string => 'foo')
125
+ extended_record = ActiveType::Util.cast(base_record, UtilSpec::ExtendedRecord)
126
+ expect {
127
+ value = extended_record.virtual_string_for_validation
128
+ extended_record.errors.add(:virtual_string_for_validation, :empty) if value.nil? || value.empty?
129
+ }.not_to raise_error
130
+ expect(extended_record.errors.size).to eq 1
131
+ expect(base_record.errors.size).to eq 0
132
+ end
133
+
120
134
  end
121
135
 
122
136
  end
@@ -1,21 +1,4 @@
1
- class User < ::ActiveRecord::Base
2
- end
3
-
4
- class Foo < ::ActiveType::Record[User]
5
- def new
6
- allocate
7
- end
8
- end
9
-
10
-
11
1
  shared_examples_for "ActiveRecord-like accessors" do |attributes|
12
- it 'setup the virtual_attributes instance variable lazy' do
13
- expect(Foo.new.virtual_attributes).to eq({})
14
- end
15
-
16
- it 'setup the virtual_attributes_cache instance variable lazy' do
17
- expect(Foo.new.virtual_attributes_cache).to eq({})
18
- end
19
2
 
20
3
  it 'allows to read and write' do
21
4
  attributes.each do |key, value|
@@ -115,7 +115,7 @@ shared_examples_for 'a coercible time column' do |column|
115
115
  end
116
116
 
117
117
  it 'leaves times alone' do
118
- time = Time.now
118
+ time = Time.at(Time.now.to_i)
119
119
  subject.send(:"#{column}=", time)
120
120
 
121
121
  expect(subject.send(column)).to eq(time)
@@ -226,3 +226,23 @@ shared_examples_for 'an untyped column' do |column|
226
226
  expect(subject.send(column)).to eq(object)
227
227
  end
228
228
  end
229
+
230
+
231
+ shared_examples_for 'a coercible type column' do |column, type|
232
+
233
+ if type
234
+
235
+ it 'is nil by default' do
236
+ expect(subject.send(column)).to be_nil
237
+ end
238
+
239
+ it 'leaves strings alone' do
240
+ expect(type).to receive(:cast).with('input').and_return('output')
241
+ subject.send(:"#{column}=", 'input')
242
+
243
+ expect(subject.send(column)).to eq('output')
244
+ end
245
+
246
+ end
247
+
248
+ 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.5.0
4
+ version: 0.6.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: 2016-04-08 00:00:00.000000000 Z
12
+ date: 2016-07-05 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -60,6 +60,7 @@ extensions: []
60
60
  extra_rdoc_files: []
61
61
  files:
62
62
  - ".gitignore"
63
+ - ".rspec"
63
64
  - ".ruby-version"
64
65
  - ".travis.yml"
65
66
  - CHANGELOG.md
@@ -81,6 +82,12 @@ files:
81
82
  - gemfiles/Gemfile.4.2.1.pg.lock
82
83
  - gemfiles/Gemfile.4.2.1.sqlite3
83
84
  - gemfiles/Gemfile.4.2.1.sqlite3.lock
85
+ - gemfiles/Gemfile.5.0.0.mysql2
86
+ - gemfiles/Gemfile.5.0.0.mysql2.lock
87
+ - gemfiles/Gemfile.5.0.0.pg
88
+ - gemfiles/Gemfile.5.0.0.pg.lock
89
+ - gemfiles/Gemfile.5.0.0.sqlite3
90
+ - gemfiles/Gemfile.5.0.0.sqlite3.lock
84
91
  - lib/active_type.rb
85
92
  - lib/active_type/extended_record.rb
86
93
  - lib/active_type/extended_record/inheritance.rb
@@ -133,7 +140,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
133
140
  requirements:
134
141
  - - ">="
135
142
  - !ruby/object:Gem::Version
136
- version: '0'
143
+ version: 1.9.3
137
144
  required_rubygems_version: !ruby/object:Gem::Requirement
138
145
  requirements:
139
146
  - - ">="
@@ -141,7 +148,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
141
148
  version: '0'
142
149
  requirements: []
143
150
  rubyforge_project:
144
- rubygems_version: 2.4.8
151
+ rubygems_version: 2.4.5.1
145
152
  signing_key:
146
153
  specification_version: 4
147
154
  summary: Make any Ruby object quack like ActiveRecord