active_type 0.4.5 → 0.7.5

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.
Files changed (69) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rspec +1 -0
  4. data/.travis.yml +30 -24
  5. data/CHANGELOG.md +73 -2
  6. data/README.md +56 -11
  7. data/Rakefile +22 -1
  8. data/active_type.gemspec +2 -1
  9. data/gemfiles/Gemfile.3.2.mysql2 +1 -0
  10. data/gemfiles/Gemfile.3.2.mysql2.lock +4 -2
  11. data/gemfiles/Gemfile.3.2.sqlite3 +1 -0
  12. data/gemfiles/Gemfile.3.2.sqlite3.lock +4 -2
  13. data/gemfiles/Gemfile.4.0.sqlite3 +1 -0
  14. data/gemfiles/Gemfile.4.0.sqlite3.lock +4 -2
  15. data/gemfiles/Gemfile.4.1.sqlite3 +1 -0
  16. data/gemfiles/Gemfile.4.1.sqlite3.lock +4 -2
  17. data/gemfiles/Gemfile.4.2.1.mysql2 +1 -0
  18. data/gemfiles/Gemfile.4.2.1.mysql2.lock +4 -2
  19. data/gemfiles/Gemfile.4.2.1.pg +1 -0
  20. data/gemfiles/Gemfile.4.2.1.pg.lock +4 -2
  21. data/gemfiles/Gemfile.4.2.1.sqlite3 +1 -0
  22. data/gemfiles/Gemfile.4.2.1.sqlite3.lock +4 -2
  23. data/gemfiles/Gemfile.5.0.0.mysql2.lock +56 -0
  24. data/gemfiles/Gemfile.5.0.0.pg.lock +56 -0
  25. data/gemfiles/Gemfile.5.0.0.sqlite3 +8 -0
  26. data/gemfiles/Gemfile.5.0.0.sqlite3.lock +56 -0
  27. data/gemfiles/Gemfile.5.1.0.mysql2 +8 -0
  28. data/gemfiles/Gemfile.5.1.0.mysql2.lock +56 -0
  29. data/gemfiles/Gemfile.5.1.0.pg +8 -0
  30. data/gemfiles/Gemfile.5.1.0.pg.lock +56 -0
  31. data/gemfiles/Gemfile.5.1.0.sqlite3 +8 -0
  32. data/gemfiles/Gemfile.5.1.0.sqlite3.lock +56 -0
  33. data/lib/active_type/extended_record/inheritance.rb +41 -6
  34. data/lib/active_type/nested_attributes/association.rb +13 -4
  35. data/lib/active_type/nested_attributes/builder.rb +3 -3
  36. data/lib/active_type/nested_attributes/nests_many_association.rb +5 -1
  37. data/lib/active_type/nested_attributes/nests_one_association.rb +3 -2
  38. data/lib/active_type/no_table.rb +129 -42
  39. data/lib/active_type/type_caster.rb +66 -25
  40. data/lib/active_type/util.rb +21 -6
  41. data/lib/active_type/version.rb +1 -1
  42. data/lib/active_type/virtual_attributes.rb +23 -1
  43. data/lib/active_type.rb +13 -3
  44. metadata +16 -55
  45. data/spec/active_type/extended_record/single_table_inheritance_spec.rb +0 -62
  46. data/spec/active_type/extended_record_spec.rb +0 -233
  47. data/spec/active_type/nested_attributes_spec.rb +0 -700
  48. data/spec/active_type/object_spec.rb +0 -400
  49. data/spec/active_type/record_spec.rb +0 -236
  50. data/spec/active_type/util_spec.rb +0 -128
  51. data/spec/integration/holidays_spec.rb +0 -102
  52. data/spec/integration/shape_spec.rb +0 -110
  53. data/spec/integration/sign_in_spec.rb +0 -101
  54. data/spec/integration/sign_up_spec.rb +0 -102
  55. data/spec/shared_examples/accessors.rb +0 -41
  56. data/spec/shared_examples/belongs_to.rb +0 -17
  57. data/spec/shared_examples/coercible_columns.rb +0 -228
  58. data/spec/shared_examples/constructor.rb +0 -30
  59. data/spec/shared_examples/defaults.rb +0 -60
  60. data/spec/shared_examples/dirty_tracking.rb +0 -40
  61. data/spec/shared_examples/dupable.rb +0 -31
  62. data/spec/shared_examples/mass_assignment.rb +0 -26
  63. data/spec/spec_helper.rb +0 -27
  64. data/spec/support/database.rb +0 -55
  65. data/spec/support/database.sample.yml +0 -3
  66. data/spec/support/error_on.rb +0 -12
  67. data/spec/support/i18n.rb +0 -1
  68. data/spec/support/protected_params.rb +0 -20
  69. data/spec/support/time_zone.rb +0 -1
@@ -1,228 +0,0 @@
1
- module TimeConversionSpec
2
- class Record < ActiveRecord::Base
3
- end
4
- end
5
-
6
- shared_examples_for 'a coercible string column' do |column|
7
-
8
- it 'is nil by default' do
9
- expect(subject.send(column)).to be_nil
10
- end
11
-
12
- it 'leaves strings alone' do
13
- subject.send(:"#{column}=", "string")
14
-
15
- expect(subject.send(column)).to eq("string")
16
- end
17
-
18
- it 'does not convert blank' do
19
- subject.send(:"#{column}=", "")
20
-
21
- expect(subject.send(column)).to eq("")
22
- end
23
-
24
- end
25
-
26
-
27
- shared_examples_for 'a coercible integer column' do |column|
28
-
29
- it 'is nil by default' do
30
- expect(subject.send(column)).to be_nil
31
- end
32
-
33
- it 'leaves integers alone' do
34
- subject.send(:"#{column}=", 10)
35
-
36
- expect(subject.send(column)).to eq(10)
37
- end
38
-
39
- it 'converts strings to integers' do
40
- subject.send(:"#{column}=", "10")
41
-
42
- expect(subject.send(column)).to eq(10)
43
- end
44
-
45
- it 'converts blank to nil' do
46
- subject.send(:"#{column}=", "")
47
-
48
- expect(subject.send(column)).to be_nil
49
- end
50
-
51
- end
52
-
53
-
54
- shared_examples_for 'a coercible date column' do |column|
55
-
56
- it 'is nil by default' do
57
- expect(subject.send(column)).to be_nil
58
- end
59
-
60
- it 'leaves dates alone' do
61
- date = Date.today
62
- subject.send(:"#{column}=", date)
63
-
64
- expect(subject.send(column)).to eq(date)
65
- end
66
-
67
- it 'converts strings to dates' do
68
- subject.send(:"#{column}=", "2010-10-01")
69
-
70
- expect(subject.send(column)).to eq(Date.new(2010, 10, 1))
71
- end
72
-
73
- it 'converts blank to nil' do
74
- subject.send(:"#{column}=", "")
75
-
76
- expect(subject.send(column)).to be_nil
77
- end
78
-
79
- end
80
-
81
-
82
- shared_examples_for 'a coercible time column' do |column|
83
-
84
- around do |example|
85
- begin
86
- old_time_zone = Time.zone
87
- old_time_zone_aware_attributes = ActiveRecord::Base.time_zone_aware_attributes
88
- old_default_timezone = ActiveRecord::Base.default_timezone
89
- example.run
90
- ensure
91
- Time.zone = old_time_zone
92
- ActiveRecord::Base.time_zone_aware_attributes = old_time_zone_aware_attributes
93
- ActiveRecord::Base.default_timezone = old_default_timezone
94
- subject.class.reset_column_information
95
- end
96
- end
97
-
98
- def it_should_convert_like_active_record(column)
99
- time = "2010-10-01 12:15"
100
- TimeConversionSpec::Record.reset_column_information
101
- subject.class.reset_column_information
102
-
103
- comparison = TimeConversionSpec::Record.new
104
- subject.send(:"#{column}=", time)
105
- comparison.persisted_time = time
106
-
107
- result = subject.send(column)
108
- expect(result).to eq(comparison.persisted_time)
109
- expect(result.zone).to eq(comparison.persisted_time.zone)
110
- end
111
-
112
-
113
- it 'is nil by default' do
114
- expect(subject.send(column)).to be_nil
115
- end
116
-
117
- it 'leaves times alone' do
118
- time = Time.now
119
- subject.send(:"#{column}=", time)
120
-
121
- expect(subject.send(column)).to eq(time)
122
- end
123
-
124
- it 'converts strings to times' do
125
- subject.send(:"#{column}=", "2010-10-01 12:15")
126
-
127
- expect(subject.send(column)).to eq(Time.local(2010, 10, 1, 12, 15))
128
- end
129
-
130
- it 'behaves consistently with ActiveRecord' do
131
- Time.zone = 'Hawaii'
132
-
133
- it_should_convert_like_active_record(column)
134
- end
135
-
136
- it 'behaves consistently with ActiveRecord if time_zone_aware_attributes is set' do
137
- Time.zone = 'Hawaii'
138
- ActiveRecord::Base.time_zone_aware_attributes = true
139
-
140
- it_should_convert_like_active_record(column)
141
- end
142
-
143
- it 'behaves consistently with ActiveRecord if default_timezone is :utc' do
144
- Time.zone = 'Hawaii'
145
- ActiveRecord::Base.default_timezone = :utc
146
-
147
- it_should_convert_like_active_record(column)
148
- end
149
-
150
- it 'behaves consistently with ActiveRecord if time_zone_aware_attributes is set, default_timezone is :utc' do
151
- Time.zone = 'Hawaii'
152
- ActiveRecord::Base.default_timezone = :utc
153
- ActiveRecord::Base.time_zone_aware_attributes = true
154
-
155
- it_should_convert_like_active_record(column)
156
- end
157
-
158
- end
159
-
160
-
161
- shared_examples_for 'a coercible boolean column' do |column|
162
-
163
- it 'is nil by default' do
164
- expect(subject.send(column)).to be_nil
165
- end
166
-
167
- it 'leaves booleans alone' do
168
- subject.send(:"#{column}=", true)
169
-
170
- expect(subject.send(column)).to eq(true)
171
- end
172
-
173
- it 'converts 1 to true' do
174
- subject.send(:"#{column}=", "1")
175
-
176
- expect(subject.send(column)).to eq(true)
177
- end
178
-
179
- it 'converts 0 to false' do
180
- subject.send(:"#{column}=", "0")
181
-
182
- expect(subject.send(column)).to eq(false)
183
- end
184
-
185
- it 'converts "" to nil' do
186
- subject.send(:"#{column}=", "")
187
-
188
- expect(subject.send(column)).to be_nil
189
- end
190
-
191
- it 'converts "true" to true' do
192
- subject.send(:"#{column}=", "true")
193
-
194
- expect(subject.send(column)).to eq(true)
195
- end
196
-
197
- it 'converts "false" to false' do
198
- subject.send(:"#{column}=", "false")
199
-
200
- expect(subject.send(column)).to eq(false)
201
- end
202
-
203
- end
204
-
205
- shared_examples_for 'an untyped column' do |column|
206
- it 'is nil by default' do
207
- expect(subject.send(column)).to be_nil
208
- end
209
-
210
- it 'leaves strings alone' do
211
- subject.send(:"#{column}=", "string")
212
-
213
- expect(subject.send(column)).to eq("string")
214
- end
215
-
216
- it 'leaves integers alone' do
217
- subject.send(:"#{column}=", 17)
218
-
219
- expect(subject.send(column)).to eq(17)
220
- end
221
-
222
- it 'leaves objects alone' do
223
- object = Object.new
224
- subject.send(:"#{column}=", object)
225
-
226
- expect(subject.send(column)).to eq(object)
227
- end
228
- end
@@ -1,30 +0,0 @@
1
- shared_examples_for 'ActiveRecord-like constructors' do |attributes|
2
-
3
- it 'return a new record' do
4
- expect(subject.new).to be_new_record
5
- end
6
-
7
- it 'assigns given attributes' do
8
- record = subject.new(attributes)
9
-
10
- attributes.each do |key, value|
11
- expect(record.send(key)).to eq(value)
12
- end
13
- end
14
-
15
- if ActiveRecord::VERSION::MAJOR >= 4
16
-
17
- it 'raises on unpermitted parameters' do
18
- params = ProtectedParams.new(attributes)
19
- expect { subject.new(params) }.to raise_error(ActiveModel::ForbiddenAttributesError)
20
- end
21
-
22
- it 'accepts permitted parameters' do
23
- params = ProtectedParams.new(attributes)
24
- params.permit!
25
- expect { subject.new(params) }.to_not raise_error
26
- end
27
-
28
- end
29
-
30
- end
@@ -1,60 +0,0 @@
1
- shared_examples_for "a class accepting attribute defaults" do |klass|
2
-
3
- subject do
4
- Class.new(klass) do
5
- attribute :static_string, :string, :default => "static string"
6
- attribute :dynamic_string, :string, :default => proc { "dynamic string" }
7
- attribute :referential_string, :string, :default => proc { value }
8
- attribute :number, :integer, :default => "10"
9
- attribute :computed, :default => proc { compute }
10
-
11
- def value
12
- "value"
13
- end
14
-
15
- end.new
16
- end
17
-
18
- it 'can have static defaults' do
19
- expect(subject.static_string).to eq("static string")
20
- end
21
-
22
- it 'can have dynamic defaults' do
23
- expect(subject.dynamic_string).to eq("dynamic string")
24
- end
25
-
26
- it 'can have defaults refering to instance methods' do
27
- expect(subject.referential_string).to eq("value")
28
- end
29
-
30
- it 'typecasts defaults' do
31
- expect(subject.number).to eq(10)
32
- end
33
-
34
- it 'computes defaults lazily' do
35
- expect(subject).to receive(:compute).and_return("computed")
36
- expect(subject.computed).to eq("computed")
37
- end
38
-
39
- it 'does not compute defaults more than once' do
40
- expect(subject).to receive(:compute).exactly(:once).and_return(nil)
41
- subject.computed
42
- subject.computed
43
- end
44
-
45
- it 'does not compute defaults when overriden' do
46
- subject.computed = 'not computed'
47
- expect(subject.computed).to eq('not computed')
48
- end
49
-
50
- it 'does not use defaults when overriden' do
51
- subject.static_string = "my string"
52
- expect(subject.static_string).to eq("my string")
53
- end
54
-
55
- it 'does not use defaults when overriden with nil' do
56
- subject.static_string = nil
57
- expect(subject.static_string).to eq(nil)
58
- end
59
-
60
- end
@@ -1,40 +0,0 @@
1
- shared_examples_for "a class supporting dirty tracking for virtual attributes" do |klass|
2
-
3
- subject do
4
- Class.new(klass) do
5
- attribute :virtual_attribute
6
- end.new
7
- end
8
-
9
- describe '#virtual_attribute_was' do
10
-
11
- it 'always returns nil, since there can be no previously saved value' do
12
- expect(subject.virtual_attribute_was).to be_nil
13
- end
14
-
15
- end
16
-
17
- describe '#virtual_attribute_changed?' do
18
-
19
- it 'returns true if the attribute is not nil' do
20
- subject.virtual_attribute = 'foo'
21
- expect(subject.virtual_attribute_changed?).to eq(true)
22
- end
23
-
24
- it 'returns false if the attribute is nil' do
25
- subject.virtual_attribute = nil
26
- expect(subject.virtual_attribute_changed?).to be_falsey
27
- end
28
-
29
- end
30
-
31
- describe '#virtual_attribute_will_change!' do
32
-
33
- it 'is implemented for compatibility with ActiveModel::Dirty, but does nothing' do
34
- expect(subject).to respond_to(:virtual_attribute_will_change!)
35
- expect { subject.virtual_attribute_will_change! }.to_not raise_error
36
- end
37
-
38
- end
39
-
40
- end
@@ -1,31 +0,0 @@
1
- shared_examples_for "a class supporting dup for attributes" do |klass|
2
-
3
- subject do
4
- Class.new(klass) do
5
- attribute :attribute
6
- end.new
7
- end
8
-
9
- describe '#dup' do
10
-
11
- it 'returns an object with independent attributes' do
12
- subject.attribute = "foo"
13
- duped = subject.dup
14
- duped.attribute = "bar"
15
-
16
- expect(subject.attribute).to eq("foo")
17
- expect(duped.attribute).to eq("bar")
18
- end
19
-
20
- it 'does a deep copy' do
21
- subject.attribute = { :foo => "bar" }
22
- duped = subject.dup
23
- duped.attribute.merge!(:foo => "baz")
24
-
25
- expect(subject.attribute).to eq({ :foo => "bar" })
26
- expect(duped.attribute).to eq({ :foo => "baz" })
27
- end
28
-
29
- end
30
-
31
- end
@@ -1,26 +0,0 @@
1
- shared_examples_for 'ActiveRecord-like mass assignment' do |attributes|
2
-
3
- it 'assigns all given attributes' do
4
- subject.attributes = attributes
5
-
6
- attributes.each do |key, value|
7
- expect(subject.send(key)).to eq(value)
8
- end
9
- end
10
-
11
- if ActiveRecord::VERSION::MAJOR >= 4
12
-
13
- it 'raises on unpermitted parameters' do
14
- params = ProtectedParams.new(attributes)
15
- expect { subject.attributes = params }.to raise_error(ActiveModel::ForbiddenAttributesError)
16
- end
17
-
18
- it 'accepts permitted parameters' do
19
- params = ProtectedParams.new(attributes)
20
- params.permit!
21
- expect { subject.attributes = params }.to_not raise_error
22
- end
23
-
24
- end
25
-
26
- end
data/spec/spec_helper.rb DELETED
@@ -1,27 +0,0 @@
1
- # encoding: utf-8
2
-
3
- $: << File.join(File.dirname(__FILE__), "/../../lib" )
4
-
5
- require 'active_type'
6
-
7
- ActiveRecord::Base.default_timezone = :local
8
-
9
- Dir["#{File.dirname(__FILE__)}/support/*.rb"].each {|f| require f}
10
- Dir["#{File.dirname(__FILE__)}/shared_examples/*.rb"].each {|f| require f}
11
-
12
-
13
- RSpec.configure do |config|
14
- config.around do |example|
15
- if example.metadata.fetch(:rollback, true)
16
- ActiveRecord::Base.transaction do
17
- begin
18
- example.run
19
- ensure
20
- raise ActiveRecord::Rollback
21
- end
22
- end
23
- else
24
- example.run
25
- end
26
- end
27
- end
@@ -1,55 +0,0 @@
1
- require 'yaml'
2
-
3
- # pg?
4
- case ENV['BUNDLE_GEMFILE']
5
- when /pg/
6
- if ENV['TRAVIS']
7
- ActiveRecord::Base.establish_connection(:adapter => 'postgresql', :database => 'active_type_test', :username => 'postgres')
8
- else
9
- ActiveRecord::Base.establish_connection(:adapter => 'postgresql', :database => 'active_type_test')
10
- end
11
- # mysql2?
12
- when /mysql2/
13
- config = { :adapter => 'mysql2', :encoding => 'utf8', :database => 'active_type_test' }
14
- custom_config_path = File.join(File.dirname(__FILE__), 'database.yml')
15
- if File.exists?(custom_config_path)
16
- custom_config = YAML.load_file(custom_config_path)
17
- config.merge!(custom_config)
18
- end
19
- ActiveRecord::Base.establish_connection(config)
20
- when /sqlite3/
21
- ActiveRecord::Base.establish_connection(:adapter => 'sqlite3', :database => ':memory:')
22
- else
23
- raise "Unknown database type in Gemfile suffix: #{ENV['BUNDLE_GEMFILE']}"
24
- end
25
-
26
-
27
- connection = ::ActiveRecord::Base.connection
28
- connection.tables.each do |table|
29
- connection.drop_table table
30
- end
31
-
32
- ActiveRecord::Migration.class_eval do
33
-
34
- create_table :records do |t|
35
- t.string :persisted_string
36
- t.integer :persisted_integer
37
- t.datetime :persisted_time
38
- t.date :persisted_date
39
- t.boolean :persisted_boolean
40
- end
41
-
42
- create_table :children do |t|
43
- t.integer :record_id
44
- end
45
-
46
- create_table :sti_records do |t|
47
- t.string :persisted_string
48
- t.string :type
49
- end
50
-
51
- create_table :other_records do |t|
52
- t.string :other_string
53
- end
54
-
55
- end
@@ -1,3 +0,0 @@
1
- host: localhost
2
- username: joe
3
- password: secret
@@ -1,12 +0,0 @@
1
- module ActiveModel::Validations
2
-
3
- def errors_on(attribute, options = {})
4
- valid_args = [options[:context]].compact
5
- self.valid?(*valid_args)
6
-
7
- [self.errors[attribute]].flatten.compact
8
- end
9
-
10
- alias :error_on :errors_on
11
-
12
- end
data/spec/support/i18n.rb DELETED
@@ -1 +0,0 @@
1
- I18n.enforce_available_locales = false
@@ -1,20 +0,0 @@
1
- class ProtectedParams < ActiveSupport::HashWithIndifferentAccess
2
- attr_accessor :permitted
3
- alias :permitted? :permitted
4
-
5
- def initialize(attributes)
6
- super(attributes)
7
- @permitted = false
8
- end
9
-
10
- def permit!
11
- @permitted = true
12
- self
13
- end
14
-
15
- def dup
16
- super.tap do |duplicate|
17
- duplicate.instance_variable_set :@permitted, @permitted
18
- end
19
- end
20
- end
@@ -1 +0,0 @@
1
- require 'active_support/time'