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 +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
|