HornsAndHooves-moribus 0.1.0 → 0.2.0
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/.simplecov +1 -1
- data/Gemfile +5 -1
- data/HornsAndHooves-moribus.gemspec +1 -1
- data/lib/moribus/alias_association.rb +9 -3
- data/lib/moribus/macros.rb +4 -0
- data/lib/moribus/tracked_behavior.rb +9 -7
- data/lib/moribus/version.rb +2 -2
- data/spec/moribus/alias_association_spec.rb +19 -19
- data/spec/moribus_spec.rb +38 -38
- metadata +12 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ff0aab79e8583ad02f5eeea9b364f1675d893399
|
4
|
+
data.tar.gz: 2c299a91b8eb26c99a91896b01100dcd04626409
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c66b62b01b54222d549dbd8e038d3b073cf850a9f394450dcde325bf32d644e796ce234720c53cbebd1c0f8cd156a5479571b5d59021798fc5b48f1a5ecdbbe8
|
7
|
+
data.tar.gz: 86c8695bd44971914bc00f5f60fd72a1a697a1625810cafd9575b2287ee3e2112b74b0c51e92411868609e5f3e3d48dba35e2bf81c032216efbf40fd9f1d2a16
|
data/.simplecov
CHANGED
@@ -12,7 +12,7 @@ SimpleCov.start do
|
|
12
12
|
# Fail the build when coverage is weak:
|
13
13
|
at_exit do
|
14
14
|
SimpleCov.result.format!
|
15
|
-
threshold, actual =
|
15
|
+
threshold, actual = 97.118, SimpleCov.result.covered_percent
|
16
16
|
if actual < threshold
|
17
17
|
msg = "\nLow coverage: "
|
18
18
|
msg << red("#{actual}%")
|
data/Gemfile
CHANGED
@@ -3,10 +3,14 @@ source "https://rubygems.org"
|
|
3
3
|
# Specify your gem's dependencies in moribus.gemspec
|
4
4
|
gemspec
|
5
5
|
|
6
|
+
group :development, :test do
|
7
|
+
gem "pry"
|
8
|
+
gem "pry-nav"
|
9
|
+
end
|
10
|
+
|
6
11
|
group :development do
|
7
12
|
gem "redcarpet"
|
8
13
|
gem "yard"
|
9
|
-
gem "pry"
|
10
14
|
end
|
11
15
|
|
12
16
|
group :test do
|
@@ -20,7 +20,7 @@ Gem::Specification.new do |s|
|
|
20
20
|
s.require_paths = ["lib"]
|
21
21
|
|
22
22
|
# specify any dependencies here; for example:
|
23
|
-
s.add_dependency "rails", "
|
23
|
+
s.add_dependency "rails", "> 4.0", "< 4.2"
|
24
24
|
s.add_dependency "power_enum", ">= 2.7.0"
|
25
25
|
s.add_dependency "yard", ">= 0"
|
26
26
|
|
@@ -19,11 +19,17 @@ module Moribus
|
|
19
19
|
|
20
20
|
# Class methods for ActiveRecord::Base
|
21
21
|
module ClassMethods
|
22
|
-
# Aliases association reflection in reflections hash and
|
23
|
-
# association-specific methods. See module description for example
|
22
|
+
# Aliases association reflection in ActiveRecord's (internal) reflections hash and
|
23
|
+
# association-specific methods. See module description for example.
|
24
24
|
def alias_association(alias_name, association_name)
|
25
25
|
if reflection = reflect_on_association(association_name)
|
26
|
-
|
26
|
+
# Use Rails 4.1.x+ behavior, if available:
|
27
|
+
if ActiveRecord::Reflection.respond_to? :add_reflection then
|
28
|
+
ActiveRecord::Reflection.add_reflection self, alias_name, reflection
|
29
|
+
else
|
30
|
+
# Rails 4.0.x behavior:
|
31
|
+
reflections[alias_name] = reflection
|
32
|
+
end
|
27
33
|
alias_association_methods(alias_name, reflection)
|
28
34
|
reflection
|
29
35
|
end
|
data/lib/moribus/macros.rb
CHANGED
@@ -92,6 +92,8 @@ module Moribus
|
|
92
92
|
end
|
93
93
|
|
94
94
|
reflection = has_one(name, scope, options)
|
95
|
+
# Rails 4.1 compatibility fix:
|
96
|
+
reflection = reflection[name] if reflection.respond_to? :[]
|
95
97
|
reflection.options[:is_current] = true
|
96
98
|
accepts_nested_attributes_for name
|
97
99
|
define_effective_reader_for name
|
@@ -106,6 +108,8 @@ module Moribus
|
|
106
108
|
# Extensions::HasAggregatedExtension)
|
107
109
|
def has_aggregated(name, options = {})
|
108
110
|
reflection = belongs_to(name, options)
|
111
|
+
# Rails 4.1 compatibility fix:
|
112
|
+
reflection = reflection[name] if reflection.respond_to? :[]
|
109
113
|
reflection.options[:aggregated] = true
|
110
114
|
accepts_nested_attributes_for name
|
111
115
|
define_effective_reader_for name
|
@@ -77,13 +77,15 @@ module Moribus
|
|
77
77
|
|
78
78
|
# Generate SQL statement to be used to update 'is_current' state of record to false.
|
79
79
|
def current_to_false_sql_statement
|
80
|
-
klass
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
sql << "
|
80
|
+
klass = self.class
|
81
|
+
is_current_col = klass.columns.detect{|c| c.name == "is_current" }
|
82
|
+
lock_col = klass.locking_column
|
83
|
+
lock_value = respond_to?(lock_col) && send(lock_col).to_i
|
84
|
+
quoted_lock_col = klass.connection.quote_column_name(lock_col)
|
85
|
+
"UPDATE #{klass.quoted_table_name} SET \"is_current\" = #{klass.quote_value(false, is_current_col)} ".tap do |sql|
|
86
|
+
sql << ", #{quoted_lock_col} = #{klass.quote_value(lock_value + 1, lock_col)} " if lock_value
|
87
|
+
sql << "WHERE #{klass.quoted_primary_key} = #{klass.quote_value(@_before_to_new_record_values[:id], "id")} "
|
88
|
+
sql << "AND #{quoted_lock_col} = #{klass.quote_value(lock_value, lock_col)}" if lock_value
|
87
89
|
end
|
88
90
|
end
|
89
91
|
private :current_to_false_sql_statement
|
data/lib/moribus/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
1
|
module Moribus # :nodoc:
|
2
|
-
VERSION = "0.
|
3
|
-
end
|
2
|
+
VERSION = "0.2.0" # :nodoc:
|
3
|
+
end
|
@@ -38,51 +38,51 @@ describe Moribus::AliasAssociation do
|
|
38
38
|
|
39
39
|
describe "reflection aliasing" do
|
40
40
|
it "alias association name in reflections" do
|
41
|
-
SpecPost.reflect_on_association(:author).
|
41
|
+
expect(SpecPost.reflect_on_association(:author)).not_to be_nil
|
42
42
|
end
|
43
43
|
|
44
44
|
it "should not raise error when using aliased name in scopes" do
|
45
45
|
expect{
|
46
46
|
SpecPost.includes(:comments).first
|
47
|
-
}.
|
47
|
+
}.not_to raise_error
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
51
51
|
describe "association accessor alias methods" do
|
52
52
|
subject{ @post }
|
53
53
|
|
54
|
-
it{
|
55
|
-
it{
|
56
|
-
it{
|
57
|
-
it{
|
58
|
-
it{
|
59
|
-
it{
|
54
|
+
it{ is_expected.to respond_to :author }
|
55
|
+
it{ is_expected.to respond_to :author= }
|
56
|
+
it{ is_expected.to respond_to :comments }
|
57
|
+
it{ is_expected.to respond_to :comments= }
|
58
|
+
it{ is_expected.to respond_to :post_info }
|
59
|
+
it{ is_expected.to respond_to :post_info= }
|
60
60
|
end
|
61
61
|
|
62
62
|
describe "singular association alias method" do
|
63
63
|
subject{ @post }
|
64
64
|
|
65
|
-
it{
|
66
|
-
it{
|
67
|
-
it{
|
65
|
+
it{ is_expected.to respond_to :build_author }
|
66
|
+
it{ is_expected.to respond_to :create_author }
|
67
|
+
it{ is_expected.to respond_to :create_author! }
|
68
68
|
|
69
|
-
it{
|
70
|
-
it{
|
71
|
-
it{
|
69
|
+
it{ is_expected.to respond_to :build_post_info }
|
70
|
+
it{ is_expected.to respond_to :create_post_info }
|
71
|
+
it{ is_expected.to respond_to :create_post_info! }
|
72
72
|
end
|
73
73
|
|
74
74
|
describe "collection association alias method" do
|
75
75
|
subject{ @post }
|
76
76
|
|
77
|
-
it{
|
78
|
-
it{
|
77
|
+
it{ is_expected.to respond_to :comment_ids }
|
78
|
+
it{ is_expected.to respond_to :comment_ids= }
|
79
79
|
end
|
80
80
|
|
81
81
|
describe ":alias => alias_name shortcuts" do
|
82
82
|
subject{ @post }
|
83
83
|
|
84
|
-
it {
|
85
|
-
it {
|
86
|
-
it {
|
84
|
+
it { is_expected.to respond_to :creator }
|
85
|
+
it { is_expected.to respond_to :remarks }
|
86
|
+
it { is_expected.to respond_to :information }
|
87
87
|
end
|
88
88
|
end
|
data/spec/moribus_spec.rb
CHANGED
@@ -102,9 +102,9 @@ describe Moribus do
|
|
102
102
|
}.not_to change(SpecCustomerInfo, :count)
|
103
103
|
end
|
104
104
|
expect(@info.new_record?).to eq false
|
105
|
-
@info.id.
|
106
|
-
@info.updated_at.
|
107
|
-
@info.created_at.
|
105
|
+
expect(@info.id ).to eq old_id
|
106
|
+
expect(@info.updated_at ).to eq old_updated_at
|
107
|
+
expect(@info.created_at ).to eq old_created_at
|
108
108
|
end
|
109
109
|
end
|
110
110
|
|
@@ -140,7 +140,7 @@ describe Moribus do
|
|
140
140
|
it "should lookup self and replace id with existing on create" do
|
141
141
|
name = SpecPersonName.new :first_name => 'John', :last_name => 'Smith'
|
142
142
|
name.save
|
143
|
-
name.id.
|
143
|
+
expect(name.id).to eq @existing.id
|
144
144
|
end
|
145
145
|
|
146
146
|
it "should create a new record if lookup fails" do
|
@@ -152,7 +152,7 @@ describe Moribus do
|
|
152
152
|
it "should lookup self and replace id with existing on update" do
|
153
153
|
name = SpecPersonName.create :first_name => 'Alice', :last_name => 'Smith'
|
154
154
|
name.update_attributes :first_name => 'John'
|
155
|
-
name.id.
|
155
|
+
expect(name.id).to eq @existing.id
|
156
156
|
end
|
157
157
|
|
158
158
|
context "with caching" do
|
@@ -164,7 +164,7 @@ describe Moribus do
|
|
164
164
|
it "should lookup the existing value and add it to the cache" do
|
165
165
|
feature = SpecCustomerFeature.new :feature_name => @existing.feature_name
|
166
166
|
expect{ feature.save }.to change(SpecCustomerFeature.aggregated_records_cache, :length).by(1)
|
167
|
-
feature.id.
|
167
|
+
expect(feature.id).to eq @existing.id
|
168
168
|
end
|
169
169
|
|
170
170
|
it "should add the freshly-created record to the cache" do
|
@@ -173,12 +173,12 @@ describe Moribus do
|
|
173
173
|
|
174
174
|
it "should freeze the cached object" do
|
175
175
|
feature = SpecCustomerFeature.create(:feature_name => 'Cancelled')
|
176
|
-
SpecCustomerFeature.aggregated_records_cache[feature.feature_name].
|
176
|
+
expect(SpecCustomerFeature.aggregated_records_cache[feature.feature_name]).to be_frozen
|
177
177
|
end
|
178
178
|
|
179
179
|
it "should cache the clone of the record, not the record itself" do
|
180
180
|
feature = SpecCustomerFeature.create(:feature_name => 'Returned')
|
181
|
-
SpecCustomerFeature.aggregated_records_cache[feature.feature_name].object_id.
|
181
|
+
expect(SpecCustomerFeature.aggregated_records_cache[feature.feature_name].object_id).not_to eq feature.object_id
|
182
182
|
end
|
183
183
|
end
|
184
184
|
end
|
@@ -198,7 +198,7 @@ describe Moribus do
|
|
198
198
|
it "should replace itself with new id" do
|
199
199
|
old_id = @info.id
|
200
200
|
@info.update_attributes(:spec_person_name_id => 2)
|
201
|
-
@info.id.
|
201
|
+
expect(@info.id).not_to eq old_id
|
202
202
|
end
|
203
203
|
|
204
204
|
it "should set is_current record to false for superseded record" do
|
@@ -210,14 +210,14 @@ describe Moribus do
|
|
210
210
|
it "should set previous_id to the id of the previous record" do
|
211
211
|
old_id = @info.id
|
212
212
|
@info.update_attributes(:spec_person_name_id => 2)
|
213
|
-
@info.previous_id.
|
213
|
+
expect(@info.previous_id).to eq old_id
|
214
214
|
end
|
215
215
|
|
216
216
|
it "assigning a new current record should change is_current to false for previous one" do
|
217
217
|
new_info = SpecCustomerInfo.new :spec_person_name_id => 2, :is_current => true
|
218
218
|
@customer.spec_customer_info = new_info
|
219
|
-
new_info.spec_customer_id.
|
220
|
-
expect(@info.is_current).to eq false
|
219
|
+
expect(new_info.spec_customer_id).to eq @customer.id
|
220
|
+
expect(@info.is_current ).to eq false
|
221
221
|
end
|
222
222
|
|
223
223
|
it "should not crash on superseding with 'is_current' conditional constraint" do
|
@@ -234,14 +234,14 @@ describe Moribus do
|
|
234
234
|
|
235
235
|
it "should be updated on change" do
|
236
236
|
info = @customer.create_spec_customer_info :spec_person_name_id => 1
|
237
|
-
info.updated_at.
|
238
|
-
info.created_at.
|
237
|
+
expect(info.updated_at).to eq first_time
|
238
|
+
expect(info.created_at).to eq first_time
|
239
239
|
|
240
240
|
Timecop.freeze(second_time)
|
241
241
|
info.spec_person_name_id = 2
|
242
242
|
info.save!
|
243
|
-
info.updated_at.
|
244
|
-
info.created_at.
|
243
|
+
expect(info.updated_at).to eq second_time
|
244
|
+
expect(info.created_at).to eq second_time
|
245
245
|
end
|
246
246
|
end
|
247
247
|
|
@@ -274,8 +274,8 @@ describe Moribus do
|
|
274
274
|
old_id = @info.id
|
275
275
|
@customer.spec_customer_info.spec_person_name.first_name = 'Alice'
|
276
276
|
expect{ @customer.save }.to change(@info, :spec_person_name_id)
|
277
|
-
@info.id.
|
278
|
-
@info.is_current.
|
277
|
+
expect(@info.id).not_to eq old_id
|
278
|
+
expect(@info.is_current).to eq true
|
279
279
|
expect(SpecCustomerInfo.find(old_id).is_current).to eq false
|
280
280
|
end
|
281
281
|
end
|
@@ -290,39 +290,39 @@ describe Moribus do
|
|
290
290
|
end
|
291
291
|
|
292
292
|
it "should have delegated column information" do
|
293
|
-
@customer.column_for_attribute(:first_name).
|
293
|
+
expect(@customer.column_for_attribute(:first_name)).not_to be_nil
|
294
294
|
end
|
295
295
|
|
296
296
|
it "should not delegate special methods" do
|
297
|
-
@customer.
|
298
|
-
@customer.
|
299
|
-
@customer.
|
300
|
-
@customer.
|
301
|
-
@customer.
|
302
|
-
@customer.
|
297
|
+
expect(@customer).not_to respond_to(:reset_first_name)
|
298
|
+
expect(@customer).not_to respond_to(:first_name_was)
|
299
|
+
expect(@customer).not_to respond_to(:first_name_before_type_cast)
|
300
|
+
expect(@customer).not_to respond_to(:first_name_will_change!)
|
301
|
+
expect(@customer).not_to respond_to(:first_name_changed?)
|
302
|
+
expect(@customer).not_to respond_to(:lock_version)
|
303
303
|
end
|
304
304
|
|
305
305
|
it "should delegate methods to aggregated parts" do
|
306
|
-
@info.
|
307
|
-
@info.
|
308
|
-
@info.
|
309
|
-
@info.last_name.
|
306
|
+
expect(@info).to respond_to(:first_name)
|
307
|
+
expect(@info).to respond_to(:first_name=)
|
308
|
+
expect(@info).to respond_to(:spec_suffix)
|
309
|
+
expect(@info.last_name).to eq 'Smith'
|
310
310
|
end
|
311
311
|
|
312
312
|
it "should delegate methods to representation" do
|
313
|
-
@customer.
|
314
|
-
@customer.
|
315
|
-
@customer.
|
316
|
-
@customer.last_name.
|
317
|
-
@customer.
|
318
|
-
@customer.
|
313
|
+
expect(@customer).to respond_to(:first_name)
|
314
|
+
expect(@customer).to respond_to(:first_name=)
|
315
|
+
expect(@customer).to respond_to(:spec_suffix)
|
316
|
+
expect(@customer.last_name).to eq 'Smith'
|
317
|
+
expect(@customer).to respond_to(:custom_field)
|
318
|
+
expect(@customer).to respond_to(:custom_field=)
|
319
319
|
end
|
320
320
|
|
321
321
|
it 'should properly delegate enumerated attributes' do
|
322
|
-
@customer.
|
323
|
-
@customer.
|
322
|
+
expect(@customer).to respond_to(:spec_type)
|
323
|
+
expect(@customer).to respond_to(:spec_type=)
|
324
324
|
@customer.spec_type = :important
|
325
|
-
@customer.spec_type
|
325
|
+
expect(@customer.spec_type === :important).to eq true
|
326
326
|
end
|
327
327
|
|
328
328
|
it "should raise NoMethodError if unknown method received" do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: HornsAndHooves-moribus
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- HornsAndHooves
|
@@ -10,22 +10,28 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2015-01-20 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rails
|
17
17
|
requirement: !ruby/object:Gem::Requirement
|
18
18
|
requirements:
|
19
|
-
- - "
|
19
|
+
- - ">"
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version: 4.0
|
21
|
+
version: '4.0'
|
22
|
+
- - "<"
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: '4.2'
|
22
25
|
type: :runtime
|
23
26
|
prerelease: false
|
24
27
|
version_requirements: !ruby/object:Gem::Requirement
|
25
28
|
requirements:
|
26
|
-
- - "
|
29
|
+
- - ">"
|
30
|
+
- !ruby/object:Gem::Version
|
31
|
+
version: '4.0'
|
32
|
+
- - "<"
|
27
33
|
- !ruby/object:Gem::Version
|
28
|
-
version: 4.
|
34
|
+
version: '4.2'
|
29
35
|
- !ruby/object:Gem::Dependency
|
30
36
|
name: power_enum
|
31
37
|
requirement: !ruby/object:Gem::Requirement
|