active_record-acts_as 1.0.7 → 1.0.8
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/.travis.yml +4 -1
- data/README.md +29 -2
- data/lib/active_record/acts_as/class_methods.rb +4 -0
- data/lib/active_record/acts_as/instance_methods.rb +4 -0
- data/lib/active_record/acts_as/matchers.rb +19 -0
- data/lib/active_record/acts_as/relation.rb +4 -2
- data/lib/active_record/acts_as/version.rb +2 -2
- data/spec/acts_as_spec.rb +45 -2
- data/spec/migrations_spec.rb +1 -0
- data/spec/models.rb +25 -21
- data/spec/rspec_matchers_spec.rb +12 -0
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b9ec0528a63347a0575f88a79865139353ed16b2
|
4
|
+
data.tar.gz: 03ff53a5a895ef19f2d740e85327f93afa76dafc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d4a00877c147b27f50ecc2abaf15abe4578e2ee5cdf45b2c6c3b9acbae4e2bc3f78700bbb0da94e07ed36d685a707bd71033759e88a07b5added7b22c89d01bb
|
7
|
+
data.tar.gz: cfd9cd5ba545e01f676f418c09b5cb161d83428c44869e8dd95f28f014c71474a93a469004dffb987c9460093603ff2a2673e90df9604aaaa61c6541c83b14a7
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -86,8 +86,13 @@ change_table :products do |t|
|
|
86
86
|
end
|
87
87
|
```
|
88
88
|
|
89
|
-
|
90
|
-
|
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 )
|
@@ -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 -> {
|
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
|
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
|
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('
|
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('
|
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
|
|
data/spec/migrations_spec.rb
CHANGED
@@ -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
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
57
|
+
def initialize_schema
|
58
|
+
initialize_database do
|
59
|
+
create_table :pens do |t|
|
60
|
+
t.string :color
|
61
|
+
end
|
61
62
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
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
|
-
|
71
|
-
|
72
|
-
|
72
|
+
create_table :stores do |t|
|
73
|
+
t.string :name
|
74
|
+
end
|
73
75
|
|
74
|
-
|
75
|
-
|
76
|
-
|
76
|
+
create_table :inventory_pen_lids do |t|
|
77
|
+
t.string :color
|
78
|
+
end
|
77
79
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
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.
|
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:
|
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.
|
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
|