active_record-acts_as 1.0.7 → 1.0.8

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: 7387f8a9b958e1010c9c86367631e5be078d6329
4
- data.tar.gz: 31705e7f709ae00673bc2cf9bddcf72cc7a2eda9
3
+ metadata.gz: b9ec0528a63347a0575f88a79865139353ed16b2
4
+ data.tar.gz: 03ff53a5a895ef19f2d740e85327f93afa76dafc
5
5
  SHA512:
6
- metadata.gz: 507a0fd8e3609ceb749a1f8a3ee9ae051de0094fb769778a661ff91f0ed9bf0bb4f8001267c68db76f70f02f64f0c088d48533c599f40d76b12eacf1e8932b04
7
- data.tar.gz: aebd0d7c848b0f53639491582c3d29187ed0d152324d861ebfbbb0441f792c83a61f95bb8d0d8ccce6993be6f899203dc0d1c790ac523c09d16d3f55179a4e85
6
+ metadata.gz: d4a00877c147b27f50ecc2abaf15abe4578e2ee5cdf45b2c6c3b9acbae4e2bc3f78700bbb0da94e07ed36d685a707bd71033759e88a07b5added7b22c89d01bb
7
+ data.tar.gz: cfd9cd5ba545e01f676f418c09b5cb161d83428c44869e8dd95f28f014c71474a93a469004dffb987c9460093603ff2a2673e90df9604aaaa61c6541c83b14a7
data/.travis.yml CHANGED
@@ -1,5 +1,8 @@
1
1
  language: ruby
2
+ sudo: false
2
3
  rvm:
3
- - 2.1.1
4
+ - 2.3.0
5
+ - 2.2.3
6
+ - 2.1.7
4
7
  - 2.0.0
5
8
  - 1.9.3
data/README.md CHANGED
@@ -86,8 +86,13 @@ change_table :products do |t|
86
86
  end
87
87
  ```
88
88
 
89
- Now `Pen` and `Book` *acts as* `Product`, i.e. they inherit `Product`s *attributes*,
90
- *methods* and *validations*. Now you can do things like these:
89
+ **Make sure** that column names do not match on parent and subclass tables,
90
+ that will make SQL statements ambiguous and invalid!
91
+ Specially **DO NOT** use timestamps on subclasses, if you need them define them
92
+ on parent table and they will be touched after submodel updates.
93
+
94
+ Now `Pen` and `Book` **acts as** `Product`, i.e. they inherit `Product`s **attributes**,
95
+ **methods** and **validations**. Now you can do things like these:
91
96
 
92
97
  ```Ruby
93
98
  Pen.create name: 'Penie!', price: 0.8, color: 'red'
@@ -171,6 +176,28 @@ Replace `acts_as_superclass` in models with `actable` and if you where using
171
176
  `:as_relation_superclass` option on `create_table` remove it and use `t.actable` on column definitions.
172
177
 
173
178
 
179
+ ## RSpec custom matchers
180
+
181
+ To use this library custom RSpec matchers, you must require the `rspec/acts_as_matchers` file.
182
+
183
+ Examples:
184
+
185
+ ```Ruby
186
+ require "active_record/acts_as/matchers"
187
+
188
+ RSpec.describe "Pen acts like a Product" do
189
+ it { is_expected.to act_as(:product) }
190
+ it { is_expected.to act_as(Product) }
191
+
192
+ it { expect(Person).to act_as(:product) }
193
+ it { expect(Person).to act_as(Product) }
194
+ end
195
+
196
+ RSpec.describe "Product is actable" do
197
+ it { expect(Product).to be_actable }
198
+ end
199
+ ```
200
+
174
201
  ## Contributing
175
202
 
176
203
  1. Fork it ( https://github.com/hzamani/active_record-acts_as/fork )
@@ -9,6 +9,10 @@ module ActiveRecord
9
9
  @_reflections_acts_as_cache ||=
10
10
  _reflections_without_acts_as.reverse_merge(acting_as_model._reflections)
11
11
  end
12
+
13
+ def validators_on(*args)
14
+ super + acting_as_model.validators_on(*args)
15
+ end
12
16
  end
13
17
  end
14
18
  end
@@ -20,6 +20,10 @@ module ActiveRecord
20
20
  !acting_as.id.nil? && !acting_as_foreign_key.nil?
21
21
  end
22
22
 
23
+ def touch_actable
24
+ acting_as.touch
25
+ end
26
+
23
27
  def actable_must_be_valid
24
28
  if validates_actable
25
29
  unless acting_as.valid?
@@ -0,0 +1,19 @@
1
+ RSpec::Matchers.define :act_as do |actable|
2
+ match do |actor|
3
+ if actor.is_a?(ActiveRecord::Base)
4
+ actor.class.acting_as?(actable)
5
+ else
6
+ actor.acting_as?(actable)
7
+ end
8
+ end
9
+ end
10
+
11
+ RSpec::Matchers.define :be_actable do
12
+ match do |actable|
13
+ if actable.is_a?(ActiveRecord::Base)
14
+ actable.class.actable?
15
+ else
16
+ actable.actable?
17
+ end
18
+ end
19
+ end
@@ -12,13 +12,15 @@ module ActiveRecord
12
12
  cattr_reader(:validates_actable) { options.delete(:validates_actable) == false ? false : true }
13
13
 
14
14
  reflections = has_one name, scope, options
15
- default_scope -> { eager_load(name) }
15
+ default_scope -> { includes(name) }
16
16
  validate :actable_must_be_valid
17
+ after_update :touch_actable
17
18
 
18
19
  cattr_reader(:acting_as_reflection) { reflections.stringify_keys[name.to_s] }
19
20
  cattr_reader(:acting_as_name) { name.to_s }
20
21
  cattr_reader(:acting_as_model) { (options[:class_name] || name.to_s.camelize).constantize }
21
- class_eval "def acting_as() #{name} || build_#{name} end"
22
+ class_eval "def #{name}; super || build_#{name} end"
23
+ alias_method :acting_as, name
22
24
  alias_method :acting_as=, "#{name}=".to_sym
23
25
 
24
26
  include ActsAs::InstanceMethods
@@ -1,6 +1,6 @@
1
-
2
1
  module ActiveRecord
3
2
  module ActsAs
4
- VERSION = "1.0.7"
3
+ VERSION = "1.0.8"
5
4
  end
6
5
  end
6
+
data/spec/acts_as_spec.rb CHANGED
@@ -16,6 +16,10 @@ RSpec.describe "ActiveRecord::Base model with #acts_as called" do
16
16
  expect(association.options).to have_key(:as)
17
17
  end
18
18
 
19
+ it "autobuilds the has_one relation" do
20
+ expect(subject.new.product).not_to be_nil
21
+ end
22
+
19
23
  it "has a cattr_reader for the acting_as_model" do
20
24
  expect(subject.acting_as_model).to eq Product
21
25
  end
@@ -139,6 +143,13 @@ RSpec.describe "ActiveRecord::Base model with #acts_as called" do
139
143
  end
140
144
  end
141
145
 
146
+ describe ".validators_on" do
147
+ it "merges the validations on both superclass and subclass" do
148
+ expect(Pen.validators_on(:name, :price)).to contain_exactly(
149
+ *Product.validators_on(:name, :price))
150
+ end
151
+ end
152
+
142
153
  describe "._reflections" do
143
154
  it "merges the reflections on both superclass and subclass" do
144
155
  expect(Pen._reflections.length).to eq(Product._reflections.length + 1)
@@ -181,7 +192,18 @@ RSpec.describe "ActiveRecord::Base model with #acts_as called" do
181
192
  isolated_pen.reload
182
193
  expect(pen.option1).to eq('value1')
183
194
  expect(isolated_pen).to_not respond_to('option1')
184
- expect(JSON.parse(pen.to_json)).to eq(JSON.parse('{"id":' + pen.id.to_s + ',"name":"pen","price":0.8,"store_id":null,"settings":{"global_option":"globalvalue","option1":"value1"},"color":"red"}'))
195
+ expect(JSON.parse(pen.to_json)).to eq(JSON.parse('''
196
+ {
197
+ "id": '+ pen.id.to_s + ',
198
+ "name": "pen",
199
+ "price": 0.8,
200
+ "store_id": null,
201
+ "settings": {"global_option":"globalvalue", "option1":"value1"},
202
+ "color": "red",
203
+ "created_at": ' + pen.created_at.to_json + ',
204
+ "updated_at": ' + pen.updated_at.to_json + '
205
+ }
206
+ '''))
185
207
  end
186
208
 
187
209
  it "saves supermodel attributes on save" do
@@ -192,6 +214,15 @@ RSpec.describe "ActiveRecord::Base model with #acts_as called" do
192
214
  expect(pen.color).to eq('red')
193
215
  end
194
216
 
217
+ it "touches supermodel on save" do
218
+ pen.save
219
+ pen.reload
220
+ update = pen.product.updated_at
221
+ pen.color = "gray"
222
+ pen.save
223
+ expect(pen.updated_at).not_to eq(update)
224
+ end
225
+
195
226
  it "raises NoMethodEror on unexisting method call" do
196
227
  expect { pen.unexisted_method }.to raise_error(NoMethodError)
197
228
  end
@@ -243,10 +274,22 @@ RSpec.describe "ActiveRecord::Base model with #acts_as called" do
243
274
  it "unless the submodel instance association doesn't exist" do
244
275
  expect(JSON.parse(isolated_pen.to_json)).to eq(JSON.parse('{"id":null,"color":"red"}'))
245
276
  end
277
+
246
278
  it "if the submodel instance association exists" do
247
279
  p = Product.new(name: 'Test Pen', price: 0.8, actable: pen)
248
280
  p.save
249
- expect(JSON.parse(pen.to_json)).to eq(JSON.parse('{"id":' + pen.id.to_s + ',"name":"pen","price":0.8,"store_id":null,"settings": {},"color":"red"}'))
281
+ expect(JSON.parse(pen.to_json)).to eq(JSON.parse('''
282
+ {
283
+ "id": '+ pen.id.to_s + ',
284
+ "name": "pen",
285
+ "price": 0.8,
286
+ "store_id": null,
287
+ "settings": {},
288
+ "color": "red",
289
+ "created_at": ' + pen.created_at.to_json + ',
290
+ "updated_at": ' + pen.updated_at.to_json + '
291
+ }
292
+ '''))
250
293
  end
251
294
  end
252
295
 
@@ -8,6 +8,7 @@ end
8
8
 
9
9
  RSpec.describe ".actable" do
10
10
  context "in .create_table block" do
11
+ after { initialize_schema }
11
12
  context "with :as options" do
12
13
  it "creates plymorphic reference columns with given name" do
13
14
  initialize_database { create_table(:products) { |t| t.actable(as: :produceable) } }
data/spec/models.rb CHANGED
@@ -54,30 +54,34 @@ module Inventory
54
54
  end
55
55
  end
56
56
 
57
- initialize_database do
58
- create_table :pens do |t|
59
- t.string :color
60
- end
57
+ def initialize_schema
58
+ initialize_database do
59
+ create_table :pens do |t|
60
+ t.string :color
61
+ end
61
62
 
62
- create_table :products do |t|
63
- t.string :name
64
- t.float :price
65
- t.integer :store_id
66
- t.text :settings
67
- t.actable
68
- end
63
+ create_table :products do |t|
64
+ t.string :name
65
+ t.float :price
66
+ t.integer :store_id
67
+ t.text :settings
68
+ t.timestamps null: true
69
+ t.actable
70
+ end
69
71
 
70
- create_table :stores do |t|
71
- t.string :name
72
- end
72
+ create_table :stores do |t|
73
+ t.string :name
74
+ end
73
75
 
74
- create_table :inventory_pen_lids do |t|
75
- t.string :color
76
- end
76
+ create_table :inventory_pen_lids do |t|
77
+ t.string :color
78
+ end
77
79
 
78
- create_table :inventory_product_features do |t|
79
- t.string :name
80
- t.float :price
81
- t.actable
80
+ create_table :inventory_product_features do |t|
81
+ t.string :name
82
+ t.float :price
83
+ t.actable
84
+ end
82
85
  end
83
86
  end
87
+ initialize_schema
@@ -0,0 +1,12 @@
1
+ require 'models'
2
+ require 'active_record/acts_as/matchers'
3
+
4
+ RSpec.describe "Custom RSpec matchers" do
5
+ it { expect(Product).to be_actable }
6
+ it { expect(Product.new).to be_actable }
7
+
8
+ it { expect(Pen).to act_as(:product) }
9
+ it { expect(Pen).to act_as(Product) }
10
+ it { expect(Pen.new).to act_as(:product) }
11
+ it { expect(Pen.new).to act_as(Product) }
12
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_record-acts_as
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.7
4
+ version: 1.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hassan Zamani
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-07-21 00:00:00.000000000 Z
11
+ date: 2016-01-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sqlite3
@@ -119,6 +119,7 @@ files:
119
119
  - lib/active_record/acts_as.rb
120
120
  - lib/active_record/acts_as/class_methods.rb
121
121
  - lib/active_record/acts_as/instance_methods.rb
122
+ - lib/active_record/acts_as/matchers.rb
122
123
  - lib/active_record/acts_as/migration.rb
123
124
  - lib/active_record/acts_as/querying.rb
124
125
  - lib/active_record/acts_as/relation.rb
@@ -129,6 +130,7 @@ files:
129
130
  - spec/database_helper.rb
130
131
  - spec/migrations_spec.rb
131
132
  - spec/models.rb
133
+ - spec/rspec_matchers_spec.rb
132
134
  - spec/spec_helper.rb
133
135
  homepage: http://github.com/hzamani/active_record-acts_as
134
136
  licenses:
@@ -150,7 +152,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
150
152
  version: '0'
151
153
  requirements: []
152
154
  rubyforge_project:
153
- rubygems_version: 2.4.8
155
+ rubygems_version: 2.5.1
154
156
  signing_key:
155
157
  specification_version: 4
156
158
  summary: Simulate multi-table inheritance for activerecord models
@@ -161,4 +163,5 @@ test_files:
161
163
  - spec/database_helper.rb
162
164
  - spec/migrations_spec.rb
163
165
  - spec/models.rb
166
+ - spec/rspec_matchers_spec.rb
164
167
  - spec/spec_helper.rb