HornsAndHooves-moribus 0.4.4 → 0.5.1

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
- SHA1:
3
- metadata.gz: a9af55b2fc41dd5db61bc98f44e6a3f2b4de950d
4
- data.tar.gz: f646aafaf86ec6389dbe8b39fe3664cb2909257e
2
+ SHA256:
3
+ metadata.gz: 69f7a6978f05898888e7ef3e11471ea7606eb5211ffd7f098158bd67eec829a3
4
+ data.tar.gz: 6ac6db71051f8800f447e3dcd827abee37181754aa2f32e9ffddfd9e698392e4
5
5
  SHA512:
6
- metadata.gz: 1ad85d605b3e35f1cf1e9c62ccb94be44d02b72af11f3b7abd5b6bfbea604ffdd1e209c8cd1a95da71e35a71dfbd02a67c27088aacb14f5a22f01e4295b4ebbd
7
- data.tar.gz: a366ed36337e2516002bc426122715c49e8c4b15e58c2a8d56d479e5b1fd82de4941f23319f52bafe611f4ad07b7350684a91a1b9181dda2a140a187e19dd5d4
6
+ metadata.gz: eec5927604715080d2fd3ae72b71da0dfc4169de6949507904426f87e7a75768e4b953e07ce3efa46dfd0109fb66b743fa8e86abbb961d9ec2b971fbff480a16
7
+ data.tar.gz: 60f7975b1ad8f4818fade8a5a8f9c68d89d9244d586f6d89b6033a53fe47b7aa748378b777c9f5caa345dd90286a997f9f89d3f585901ae9f9a2c3a98427b611
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 = 96.969, SimpleCov.result.covered_percent
15
+ threshold, actual = 99.75, SimpleCov.result.covered_percent
16
16
  if actual < threshold
17
17
  msg = "\nLow coverage: "
18
18
  msg << red("#{actual}%")
data/README.md CHANGED
@@ -6,7 +6,7 @@ Moribus is a set of tools for managing complex graphs of ActiveRecord objects
6
6
  for which there are many inbound foreign keys, attributes and associations with
7
7
  high rates of change, and business demands for well-tracked change history.
8
8
 
9
- ##AggregatedBehavior
9
+ ## AggregatedBehavior
10
10
 
11
11
  AggregatedBehavior implements a pattern in which an object's identity
12
12
  is modeled apart from its attributes and outbound associations. This enables
@@ -26,7 +26,7 @@ to change. This is useful for objects with many inbound foreign keys and
26
26
  high-traffic attributes/associations, such as statuses. Without this pattern
27
27
  it would be difficult to avoid many StaleObjectErrors.
28
28
 
29
- ##TrackedBehavior
29
+ ## TrackedBehavior
30
30
 
31
31
  TrackedBehavior implements history tracking on the stack of objects
32
32
  representing the identity object's attributes and outbound associations.
@@ -36,7 +36,7 @@ and will be saved as a new record with new attribute values and the
36
36
  'is_current' column as 'true'. Thus, under the hood, new attributes
37
37
  will supersede old attributes, leaving the old record as historical.
38
38
 
39
- ##Macros, Associations and Combination
39
+ ## Macros, Associations and Combination
40
40
 
41
41
  Despite the fact that Moribus may be used by models on its own,
42
42
  its main purpose is to be used within associations, and in conjunction
@@ -105,6 +105,6 @@ rake spec
105
105
 
106
106
  ## Copyright
107
107
 
108
- Copyright (c) 2014 HornsAndHooves.
108
+ Copyright (c) 2014-2018 HornsAndHooves.
109
109
 
110
110
  Copyright (c) 2013 TMX Credit.
@@ -75,8 +75,20 @@ module Moribus
75
75
  result[parent_key] = read_attribute(parent_key)
76
76
  result
77
77
  end
78
+ relation = klass.unscoped.where(criteria)
78
79
 
79
- lock_value = klass.unscoped.where(criteria).count
80
+ sql = <<-SQL
81
+ #{relation.select("COUNT(#{lock_column_name}) AS value, 0 sort_order").to_sql}
82
+ UNION
83
+ #{relation.select("MAX(#{lock_column_name}) AS value, 1 sort_order").to_sql}
84
+ ORDER BY sort_order
85
+ SQL
86
+
87
+ result = klass.connection.execute(sql)
88
+ current_count = result[0]["value"]
89
+ current_max = result[1]["value"]
90
+
91
+ lock_value = (current_count.to_s == "0" ? 0 : current_max.to_i + 1)
80
92
 
81
93
  write_attribute(lock_column_name, lock_value)
82
94
  end
@@ -1,3 +1,3 @@
1
1
  module Moribus # :nodoc:
2
- VERSION = "0.4.4" # :nodoc:
2
+ VERSION = "0.5.1" # :nodoc:
3
3
  end
@@ -0,0 +1,131 @@
1
+ require "spec_helper"
2
+
3
+ describe Moribus::AggregatedBehavior do
4
+ before do
5
+ class SpecSuffix < MoribusSpecModel(name: :string, description: :string)
6
+ acts_as_enumerated
7
+
8
+ self.enumeration_model_updates_permitted = true
9
+ create!(name: "none", description: "")
10
+ create!(name: "jr" , description: "Junior")
11
+ end
12
+
13
+ class SpecPersonName < MoribusSpecModel(first_name: :string,
14
+ last_name: :string,
15
+ spec_suffix_id: :integer
16
+ )
17
+ acts_as_aggregated
18
+ has_enumerated :spec_suffix, default: ""
19
+
20
+ validates_presence_of :first_name, :last_name
21
+
22
+ # custom writer that additionally strips first name
23
+ def first_name=(value)
24
+ self[:first_name] = value.strip
25
+ end
26
+ end
27
+
28
+ class SpecCustomerFeature < MoribusSpecModel(feature_name: :string)
29
+ acts_as_aggregated cache_by: :feature_name
30
+ end
31
+ end
32
+
33
+ after do
34
+ MoribusSpecModel.cleanup!
35
+ end
36
+
37
+ describe "Aggregated" do
38
+ context "definition" do
39
+ it "raises an error on an unknown option" do
40
+ expect{
41
+ Class.new(ActiveRecord::Base).class_eval do
42
+ acts_as_aggregated invalid_key: :error
43
+ end
44
+ }.to raise_error(ArgumentError)
45
+ end
46
+
47
+ it "raises an error when including AggregatedCacheBehavior without AggregatedBehavior" do
48
+ expect{
49
+ Class.new(ActiveRecord::Base).class_eval do
50
+ include Moribus::AggregatedCacheBehavior
51
+ end
52
+ }.to raise_error(Moribus::AggregatedCacheBehavior::NotAggregatedError)
53
+ end
54
+ end
55
+
56
+ before do
57
+ @existing = SpecPersonName.create! first_name: "John", last_name: "Smith"
58
+ end
59
+
60
+ it "doesn't duplicate records" do
61
+ expect {
62
+ SpecPersonName.create first_name: " John ", last_name: "Smith"
63
+ }.not_to change(SpecPersonName, :count)
64
+ end
65
+
66
+ it "looks up self and replaces id with existing on create" do
67
+ name = SpecPersonName.new first_name: "John", last_name: "Smith"
68
+ name.save
69
+ expect(name.id).to eq @existing.id
70
+ end
71
+
72
+ it "creates a new record if lookup fails" do
73
+ expect {
74
+ SpecPersonName.create first_name: "Alice", last_name: "Smith"
75
+ }.to change(SpecPersonName, :count).by(1)
76
+ end
77
+
78
+ it "looks up self and replaces id with existing on update" do
79
+ name = SpecPersonName.create first_name: "Alice", last_name: "Smith"
80
+ name.update_attributes first_name: "John"
81
+ expect(name.id).to eq @existing.id
82
+ end
83
+
84
+ it "calls super in save if any aggregated behaviour non content columns wasn't changed" do
85
+ name = SpecPersonName.create first_name: "Alice", last_name: "Smith"
86
+ expect {
87
+ name.save
88
+ }.to change(SpecPersonName, :count).by(0)
89
+ end
90
+
91
+ it "raises the expected error when 'save!' fails" do
92
+ name = SpecPersonName.create first_name: "Alice", last_name: "Smith"
93
+ name.last_name = nil
94
+ expect {
95
+ name.save!
96
+ }.to raise_error(ActiveRecord::RecordNotSaved)
97
+ end
98
+
99
+ context "with caching" do
100
+ before do
101
+ @existing = SpecCustomerFeature.create(feature_name: "Pays")
102
+ SpecCustomerFeature.clear_cache
103
+ end
104
+
105
+ it "looks up the existing value and adds it to the cache" do
106
+ feature = SpecCustomerFeature.new feature_name: @existing.feature_name
107
+
108
+ expect{ feature.save }.
109
+ to change(SpecCustomerFeature.aggregated_records_cache, :length).by(1)
110
+
111
+ expect(feature.id).to eq @existing.id
112
+ end
113
+
114
+ it "adds the freshly-created record to the cache" do
115
+ expect{ SpecCustomerFeature.create(feature_name: "Fraud") }.
116
+ to change(SpecCustomerFeature.aggregated_records_cache, :length).by(1)
117
+ end
118
+
119
+ it "freezes the cached object" do
120
+ feature = SpecCustomerFeature.create(feature_name: "Cancelled")
121
+ expect(SpecCustomerFeature.aggregated_records_cache[feature.feature_name]).to be_frozen
122
+ end
123
+
124
+ it "caches the clone of the record, not the record itself" do
125
+ feature = SpecCustomerFeature.create(feature_name: "Returned")
126
+ expect(SpecCustomerFeature.aggregated_records_cache[feature.feature_name].object_id).
127
+ not_to eq feature.object_id
128
+ end
129
+ end
130
+ end
131
+ end
@@ -1,26 +1,26 @@
1
- require 'spec_helper'
1
+ require "spec_helper"
2
2
 
3
3
  describe Moribus::AliasAssociation do
4
4
  before do
5
- class SpecPost < MoribusSpecModel(:spec_author_id => :integer, :body => :string)
6
- belongs_to :spec_author , :alias => :creator
7
- has_many :spec_comments , :alias => :remarks
8
- has_one :spec_post_info, :alias => :information
5
+ class SpecPost < MoribusSpecModel(spec_author_id: :integer, body: :string)
6
+ belongs_to :spec_author , alias: :creator
7
+ has_many :spec_comments , alias: :remarks
8
+ has_one :spec_post_info, alias: :information
9
9
 
10
10
  alias_association :author , :spec_author
11
11
  alias_association :comments , :spec_comments
12
12
  alias_association :post_info, :spec_post_info
13
13
  end
14
14
 
15
- class SpecAuthor < MoribusSpecModel(:name => :string)
15
+ class SpecAuthor < MoribusSpecModel(name: :string)
16
16
  has_many :spec_posts
17
17
  end
18
18
 
19
- class SpecPostInfo < MoribusSpecModel(:spec_post_id => :integer, :ip => :string)
20
- belongs_to :spec_post, :alias => :note
19
+ class SpecPostInfo < MoribusSpecModel(spec_post_id: :integer, ip: :string)
20
+ belongs_to :spec_post, alias: :note
21
21
  end
22
22
 
23
- class SpecComment < MoribusSpecModel(:spec_post_id => :integer, :body => :string)
23
+ class SpecComment < MoribusSpecModel(spec_post_id: :integer, body: :string)
24
24
  belongs_to :spec_post
25
25
  end
26
26
  end
@@ -30,10 +30,10 @@ describe Moribus::AliasAssociation do
30
30
  end
31
31
 
32
32
  before do
33
- author = SpecAuthor.create(:name => 'John')
34
- @post = author.spec_posts.create(:body => 'Post Body')
35
- @post.spec_comments.create(:body => 'Fabulous!')
36
- @post.create_spec_post_info(:ip => '127.0.0.1')
33
+ author = SpecAuthor.create(name: "John")
34
+ @post = author.spec_posts.create(body: "Post Body")
35
+ @post.spec_comments.create(body: "Fabulous!")
36
+ @post.create_spec_post_info(ip: "127.0.0.1")
37
37
  end
38
38
 
39
39
  describe "reflection aliasing" do
@@ -41,7 +41,7 @@ describe Moribus::AliasAssociation do
41
41
  expect(SpecPost.reflect_on_association(:author)).not_to be_nil
42
42
  end
43
43
 
44
- it "should not raise error when using aliased name in scopes" do
44
+ it "does 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
@@ -0,0 +1,136 @@
1
+ require "spec_helper"
2
+
3
+ describe Moribus::Extensions::DelegateAssociated do
4
+ before do
5
+ class SpecStatus < MoribusSpecModel(name: :string, description: :string)
6
+ acts_as_enumerated
7
+
8
+ self.enumeration_model_updates_permitted = true
9
+ create!(name: "inactive", description: "Inactive")
10
+ create!(name: "active" , description: "Active")
11
+ end
12
+
13
+ class SpecType < MoribusSpecModel(name: :string, description: :string)
14
+ acts_as_enumerated
15
+
16
+ self.enumeration_model_updates_permitted = true
17
+ create!(name: "important" , description: "Important")
18
+ create!(name: "unimportant", description: "Unimportant")
19
+ end
20
+
21
+ class SpecSuffix < MoribusSpecModel(name: :string, description: :string)
22
+ acts_as_enumerated
23
+
24
+ self.enumeration_model_updates_permitted = true
25
+ create!(name: "none", description: "")
26
+ create!(name: "jr" , description: "Junior")
27
+ end
28
+
29
+ class SpecPersonName < MoribusSpecModel(first_name: :string,
30
+ middle_name: :string,
31
+ last_name: :string,
32
+ spec_suffix_id: :integer
33
+ )
34
+ acts_as_aggregated non_content_columns: :middle_name
35
+ has_enumerated :spec_suffix, default: ""
36
+
37
+ validates_presence_of :first_name, :last_name
38
+
39
+ # custom writer that additionally strips first name
40
+ def first_name=(value)
41
+ self[:first_name] = value.strip
42
+ end
43
+ end
44
+
45
+ class SpecCustomerInfo < MoribusSpecModel(
46
+ spec_customer_id: :integer!,
47
+ spec_person_name_id: :integer,
48
+ spec_status_id: :integer,
49
+ spec_type_id: :integer,
50
+ is_current: :boolean,
51
+ lock_version: :integer,
52
+ created_at: :datetime,
53
+ updated_at: :datetime,
54
+ previous_id: :integer
55
+ )
56
+ attr :custom_field
57
+
58
+ belongs_to :spec_customer, inverse_of: :spec_customer_info, touch: true
59
+ has_aggregated :spec_person_name
60
+ has_enumerated :spec_status
61
+ has_enumerated :spec_type
62
+
63
+ acts_as_tracked by: :spec_customer, preceding_key: :previous_id
64
+ end
65
+
66
+ class SpecCustomer < MoribusSpecModel(spec_status_id: :integer)
67
+ has_one_current :spec_customer_info, inverse_of: :spec_customer
68
+ has_one_current :spec_customer_info_with_type, inverse_of: :spec_customer
69
+ has_enumerated :spec_status, default: "inactive"
70
+
71
+ delegate_associated :spec_person_name, :custom_field, :spec_type, to: :spec_customer_info
72
+ end
73
+ end
74
+
75
+ after do
76
+ MoribusSpecModel.cleanup!
77
+ end
78
+
79
+ let!(:customer) do
80
+ SpecCustomer.create(
81
+ spec_customer_info_attributes: {
82
+ spec_person_name_attributes: { first_name: " John ", last_name: "Smith" }
83
+ }
84
+ )
85
+ end
86
+
87
+ let(:info) { customer.spec_customer_info }
88
+
89
+ describe "Delegations" do
90
+ it "has delegated column information" do
91
+ expect(customer.column_for_attribute(:first_name)).not_to be_nil
92
+ end
93
+
94
+ it "does not delegate special methods" do
95
+ expect(customer).not_to respond_to(:reset_first_name)
96
+ expect(customer).not_to respond_to(:first_name_was)
97
+ expect(customer).not_to respond_to(:first_name_before_type_cast)
98
+ expect(customer).not_to respond_to(:first_name_will_change!)
99
+ expect(customer).not_to respond_to(:first_name_changed?)
100
+ expect(customer).not_to respond_to(:lock_version)
101
+ end
102
+
103
+ it "delegates methods to aggregated parts" do
104
+ expect(info).to respond_to(:first_name)
105
+ expect(info).to respond_to(:first_name=)
106
+ expect(info).to respond_to(:spec_suffix)
107
+ expect(info.last_name).to eq "Smith"
108
+ end
109
+
110
+ it "delegates methods to representation" do
111
+ expect(customer).to respond_to(:first_name)
112
+ expect(customer).to respond_to(:first_name=)
113
+ expect(customer).to respond_to(:spec_suffix)
114
+ expect(customer.last_name).to eq "Smith"
115
+ expect(customer).to respond_to(:custom_field)
116
+ expect(customer).to respond_to(:custom_field=)
117
+ end
118
+
119
+ it "properly delegates enumerated attributes" do
120
+ expect(customer).to respond_to(:spec_type)
121
+ expect(customer).to respond_to(:spec_type=)
122
+ customer.spec_type = :important
123
+ expect(customer.spec_type === :important).to eq true
124
+ end
125
+
126
+ it "raises NoMethodError if unknown method is received" do
127
+ expect{ customer.impossibru }.to raise_error(NoMethodError)
128
+ end
129
+ end
130
+
131
+ describe "#column_for_attribute" do
132
+ it "returns class db column if it exists" do
133
+ expect(customer.column_for_attribute(:id)).not_to be_nil
134
+ end
135
+ end
136
+ end
@@ -0,0 +1,40 @@
1
+ require "spec_helper"
2
+
3
+ describe Moribus::Extensions::HasCurrentExtension do
4
+ before do
5
+ class SpecCustomerInfo < MoribusSpecModel(
6
+ spec_customer_id: :integer!,
7
+ is_current: :boolean,
8
+ lock_version: :integer,
9
+ created_at: :datetime,
10
+ updated_at: :datetime,
11
+ previous_id: :integer
12
+ )
13
+
14
+ belongs_to :spec_customer, inverse_of: :spec_customer_info, touch: true
15
+ end
16
+
17
+ class SpecCustomer < MoribusSpecModel(spec_status_id: :integer)
18
+ has_one_current :spec_customer_info, inverse_of: :spec_customer, dependent: :destroy
19
+ end
20
+ end
21
+
22
+ after do
23
+ MoribusSpecModel.cleanup!
24
+ end
25
+
26
+ let(:customer) { SpecCustomer.create }
27
+ let!(:info) { SpecCustomerInfo.create(spec_customer: customer, is_current: true) }
28
+
29
+ describe ".remove_target!" do
30
+ before do
31
+ allow(customer.spec_customer_info).to receive(:new_record?).and_return(true)
32
+ end
33
+
34
+ it "sets 'is_current' flag of overridden record to false for new record" do
35
+ old_info = customer.spec_customer_info
36
+ customer.spec_customer_info = SpecCustomerInfo.new
37
+ expect(old_info.is_current).to be_falsey
38
+ end
39
+ end
40
+ end
@@ -1,7 +1,101 @@
1
- require 'spec_helper'
1
+ require "spec_helper"
2
2
 
3
3
  # Some of the Moribus::Macros methods are tested in
4
4
  # spec/lib/moribus_spec.rb.
5
5
  describe Moribus::Macros do
6
+ before do
7
+ class SpecCustomer < MoribusSpecModel(spec_status_id: :integer)
8
+ has_one_current :spec_customer_info,
9
+ -> { where(spec_customer_id: 3) }, inverse_of: :spec_customer
10
+ end
6
11
 
12
+ class SpecCustomerInfo < MoribusSpecModel(
13
+ spec_customer_id: :integer!,
14
+ is_current: :boolean,
15
+ lock_version: :integer,
16
+ created_at: :datetime,
17
+ updated_at: :datetime,
18
+ previous_id: :integer
19
+ )
20
+
21
+ belongs_to :spec_customer, inverse_of: :spec_customer_info, touch: true
22
+ end
23
+
24
+ class SpecCustomerOrder < MoribusSpecModel(:spec_status_id => :integer)
25
+ has_one_current :spec_customer_info_order,
26
+ -> { order(:created_at) }, :inverse_of => :spec_customer_order
27
+ end
28
+
29
+ class SpecCustomerInfoOrder < MoribusSpecModel(
30
+ spec_customer_order_id: :integer!,
31
+ is_current: :boolean,
32
+ lock_version: :integer,
33
+ created_at: :datetime,
34
+ updated_at: :datetime,
35
+ previous_id: :integer
36
+ )
37
+
38
+ belongs_to :spec_customer_order, inverse_of: :spec_customer_info_order, touch: true
39
+ end
40
+ end
41
+
42
+ after do
43
+ MoribusSpecModel.cleanup!
44
+ end
45
+
46
+ describe ".has_one_current" do
47
+ let!(:customer) { SpecCustomer.create(id: 3, spec_status_id: 2) }
48
+ let!(:customer_order) { SpecCustomerOrder.create(id: 9, spec_status_id: 1) }
49
+
50
+ let!(:info1) do
51
+ SpecCustomerInfo.create(
52
+ spec_customer_id: 1,
53
+ is_current: true,
54
+ created_at: 5.days.ago,
55
+ updated_at: 5.days.ago
56
+ )
57
+ end
58
+
59
+ let!(:info2) do
60
+ SpecCustomerInfo.create(
61
+ spec_customer_id: 3,
62
+ is_current: true,
63
+ created_at: 5.days.ago,
64
+ updated_at: 5.days.ago
65
+ )
66
+ end
67
+
68
+ let!(:info_order1) do
69
+ SpecCustomerInfoOrder.create(
70
+ spec_customer_order_id: 9,
71
+ is_current: true,
72
+ created_at: 5.days.ago,
73
+ updated_at: 5.days.ago
74
+ )
75
+ end
76
+
77
+ let!(:info_order2) do
78
+ SpecCustomerInfoOrder.create(
79
+ spec_customer_order_id: 11,
80
+ is_current: true,
81
+ created_at: 5.days.ago,
82
+ updated_at: 5.days.ago
83
+ )
84
+ end
85
+
86
+ it "merges has_one_current scope with has_one if given" do
87
+ expect(customer.spec_customer_info ).to eq(info2)
88
+ expect(customer_order.spec_customer_info_order).to eq(info_order1)
89
+ end
90
+ end
91
+
92
+ describe ".normalize_reflection" do
93
+ subject do
94
+ SpecCustomer.send(:normalize_reflection, { spec_customer_info: :key_value }, :spec_customer_info)
95
+ end
96
+
97
+ it "returns reflection with symbol key for rails 4.1" do
98
+ is_expected.to eq(:key_value)
99
+ end
100
+ end
7
101
  end
data/spec/moribus_spec.rb CHANGED
@@ -2,36 +2,37 @@ require "spec_helper"
2
2
 
3
3
  describe Moribus do
4
4
  before do
5
- class SpecStatus < MoribusSpecModel(:name => :string, :description => :string)
5
+ class SpecStatus < MoribusSpecModel(name: :string, description: :string)
6
6
  acts_as_enumerated
7
7
 
8
8
  self.enumeration_model_updates_permitted = true
9
- create!(:name => "inactive", :description => "Inactive")
10
- create!(:name => "active" , :description => "Active")
9
+ create!(name: "inactive", description: "Inactive")
10
+ create!(name: "active" , description: "Active")
11
11
  end
12
12
 
13
- class SpecType < MoribusSpecModel(:name => :string, :description => :string)
13
+ class SpecType < MoribusSpecModel(name: :string, description: :string)
14
14
  acts_as_enumerated
15
15
 
16
16
  self.enumeration_model_updates_permitted = true
17
- create!(:name => "important" , :description => "Important")
18
- create!(:name => "unimportant", :description => "Unimportant")
17
+ create!(name: "important" , description: "Important")
18
+ create!(name: "unimportant", description: "Unimportant")
19
19
  end
20
20
 
21
- class SpecSuffix < MoribusSpecModel(:name => :string, :description => :string)
21
+ class SpecSuffix < MoribusSpecModel(name: :string, description: :string)
22
22
  acts_as_enumerated
23
23
 
24
24
  self.enumeration_model_updates_permitted = true
25
- create!(:name => "none", :description => "")
26
- create!(:name => "jr" , :description => "Junior")
25
+ create!(name: "none", description: "")
26
+ create!(name: "jr" , description: "Junior")
27
27
  end
28
28
 
29
- class SpecPersonName < MoribusSpecModel(:first_name => :string,
30
- :last_name => :string,
31
- :spec_suffix_id => :integer
29
+ class SpecPersonName < MoribusSpecModel(first_name: :string,
30
+ middle_name: :string,
31
+ last_name: :string,
32
+ spec_suffix_id: :integer
32
33
  )
33
- acts_as_aggregated
34
- has_enumerated :spec_suffix, :default => ""
34
+ acts_as_aggregated non_content_columns: :middle_name
35
+ has_enumerated :spec_suffix, default: ""
35
36
 
36
37
  validates_presence_of :first_name, :last_name
37
38
 
@@ -41,63 +42,63 @@ describe Moribus do
41
42
  end
42
43
  end
43
44
 
44
- class SpecCustomerFeature < MoribusSpecModel(:feature_name => :string)
45
- acts_as_aggregated :cache_by => :feature_name
45
+ class SpecCustomerFeature < MoribusSpecModel(feature_name: :string)
46
+ acts_as_aggregated cache_by: :feature_name
46
47
  end
47
48
 
48
49
  class SpecCustomerInfo < MoribusSpecModel(
49
- :spec_customer_id => :integer!,
50
- :spec_person_name_id => :integer,
51
- :spec_status_id => :integer,
52
- :spec_type_id => :integer,
53
- :is_current => :boolean,
54
- :lock_version => :integer,
55
- :created_at => :datetime,
56
- :updated_at => :datetime,
57
- :previous_id => :integer
50
+ spec_customer_id: :integer!,
51
+ spec_person_name_id: :integer,
52
+ spec_status_id: :integer,
53
+ spec_type_id: :integer,
54
+ is_current: :boolean,
55
+ lock_version: :integer,
56
+ created_at: :datetime,
57
+ updated_at: :datetime,
58
+ previous_id: :integer
58
59
  )
59
60
  attr :custom_field
60
61
 
61
- belongs_to :spec_customer, :inverse_of => :spec_customer_info, :touch => true
62
+ belongs_to :spec_customer, inverse_of: :spec_customer_info, touch: true
62
63
  has_aggregated :spec_person_name
63
64
  has_enumerated :spec_status
64
65
  has_enumerated :spec_type
65
66
 
66
- acts_as_tracked :by => :spec_customer, :preceding_key => :previous_id
67
+ acts_as_tracked by: :spec_customer, preceding_key: :previous_id
67
68
  end
68
69
 
69
70
  class SpecCustomerInfoWithType < MoribusSpecModel(
70
- :spec_customer_id => :integer!,
71
- :spec_status_id => :integer,
72
- :spec_type_id => :integer,
73
- :is_current => :boolean,
74
- :lock_version => :integer,
75
- :created_at => :datetime,
76
- :updated_at => :datetime
71
+ spec_customer_id: :integer!,
72
+ spec_status_id: :integer,
73
+ spec_type_id: :integer,
74
+ is_current: :boolean,
75
+ lock_version: :integer,
76
+ created_at: :datetime,
77
+ updated_at: :datetime
77
78
  )
78
79
  attr :custom_field
79
80
 
80
- belongs_to :spec_customer, :inverse_of => :spec_customer_info_with_type, :touch => true
81
+ belongs_to :spec_customer, inverse_of: :spec_customer_info_with_type, touch: true
81
82
  has_enumerated :spec_status
82
83
  has_enumerated :spec_type
83
84
 
84
85
  acts_as_tracked :by => [:spec_customer, :spec_type]
85
86
  end
86
87
 
87
- class SpecCustomer < MoribusSpecModel(:spec_status_id => :integer)
88
- has_one_current :spec_customer_info, :inverse_of => :spec_customer
89
- has_one_current :spec_customer_info_with_type, :inverse_of => :spec_customer
90
- has_enumerated :spec_status, :default => "inactive"
88
+ class SpecCustomer < MoribusSpecModel(spec_status_id: :integer)
89
+ has_one_current :spec_customer_info, inverse_of: :spec_customer
90
+ has_one_current :spec_customer_info_with_type, inverse_of: :spec_customer
91
+ has_enumerated :spec_status, default: "inactive"
91
92
 
92
- delegate_associated :spec_person_name, :custom_field, :spec_type, :to => :spec_customer_info
93
+ delegate_associated :spec_person_name, :custom_field, :spec_type, to: :spec_customer_info
93
94
  end
94
95
 
95
- class SpecCustomerEmail < MoribusSpecModel(:spec_customer_id => :integer,
96
- :email => :string,
97
- :is_current => :boolean,
98
- :status => :string
96
+ class SpecCustomerEmail < MoribusSpecModel(spec_customer_id: :integer,
97
+ email: :string,
98
+ is_current: :boolean,
99
+ status: :string
99
100
  )
100
- connection.add_index table_name, [:email, :is_current], :unique => true
101
+ connection.add_index table_name, [:email, :is_current], unique: true
101
102
 
102
103
  belongs_to :spec_customer
103
104
 
@@ -112,22 +113,22 @@ describe Moribus do
112
113
  describe "common behavior" do
113
114
  before do
114
115
  @info = SpecCustomerInfo.create(
115
- :spec_customer_id => 1,
116
- :spec_person_name_id => 1,
117
- :is_current => true,
118
- :created_at => 5.days.ago,
119
- :updated_at => 5.days.ago
116
+ spec_customer_id: 1,
117
+ spec_person_name_id: 1,
118
+ is_current: true,
119
+ created_at: 5.days.ago,
120
+ updated_at: 5.days.ago
120
121
  )
121
122
  end
122
123
 
123
- it "should revert changes if exception is raised" do
124
+ it "reverts changes if exception is raised" do
124
125
  old_id = @info.id
125
126
  old_updated_at = @info.updated_at
126
127
  old_created_at = @info.created_at
127
128
 
128
129
  suppress(Exception) do
129
130
  expect {
130
- @info.update_attributes :spec_customer_id => nil, :spec_person_name_id => 2
131
+ @info.update_attributes spec_customer_id: nil, spec_person_name_id: 2
131
132
  }.not_to change(SpecCustomerInfo, :count)
132
133
  end
133
134
 
@@ -138,130 +139,46 @@ describe Moribus do
138
139
 
139
140
  expect(@info.changed_attributes[:updated_at]).to eq(nil)
140
141
  expect(@info.changed_attributes[:created_at]).to eq(nil)
141
-
142
- end
143
- end
144
-
145
- describe "Aggregated" do
146
- context "definition" do
147
- it "should raise an error on an unknown option" do
148
- expect{
149
- Class.new(ActiveRecord::Base).class_eval do
150
- acts_as_aggregated :invalid_key => :error
151
- end
152
- }.to raise_error(ArgumentError)
153
- end
154
-
155
- it "should raise an error when including AggregatedCacheBehavior without AggregatedBehavior" do
156
- expect{
157
- Class.new(ActiveRecord::Base).class_eval do
158
- include Moribus::AggregatedCacheBehavior
159
- end
160
- }.to raise_error(Moribus::AggregatedCacheBehavior::NotAggregatedError)
161
- end
162
- end
163
-
164
- before do
165
- @existing = SpecPersonName.create! :first_name => "John", :last_name => "Smith"
166
- end
167
-
168
- it "doesn't duplicate records" do
169
- expect {
170
- SpecPersonName.create :first_name => " John ", :last_name => "Smith"
171
- }.not_to change(SpecPersonName, :count)
172
- end
173
-
174
- it "looks up self and replaces id with existing on create" do
175
- name = SpecPersonName.new :first_name => "John", :last_name => "Smith"
176
- name.save
177
- expect(name.id).to eq @existing.id
178
142
  end
179
143
 
180
- it "creates a new record if lookup fails" do
181
- expect {
182
- SpecPersonName.create :first_name => "Alice", :last_name => "Smith"
183
- }.to change(SpecPersonName, :count).by(1)
184
- end
185
-
186
- it "looks up self and replaces id with existing on update" do
187
- name = SpecPersonName.create :first_name => "Alice", :last_name => "Smith"
188
- name.update_attributes :first_name => "John"
189
- expect(name.id).to eq @existing.id
190
- end
191
-
192
- it "raises the expected error when 'save!' fails" do
193
- name = SpecPersonName.create :first_name => "Alice", :last_name => "Smith"
194
- name.last_name = nil
195
- expect {
196
- name.save!
197
- }.to raise_error(ActiveRecord::RecordNotSaved)
198
- end
199
-
200
- context "with caching" do
201
- before do
202
- @existing = SpecCustomerFeature.create(:feature_name => "Pays")
203
- SpecCustomerFeature.clear_cache
204
- end
205
-
206
- it "looks up the existing value and adds it to the cache" do
207
- feature = SpecCustomerFeature.new :feature_name => @existing.feature_name
208
-
209
- expect{ feature.save }.
210
- to change(SpecCustomerFeature.aggregated_records_cache, :length).by(1)
211
-
212
- expect(feature.id).to eq @existing.id
213
- end
214
-
215
- it "adds the freshly-created record to the cache" do
216
- expect{ SpecCustomerFeature.create(:feature_name => "Fraud") }.
217
- to change(SpecCustomerFeature.aggregated_records_cache, :length).by(1)
218
- end
219
-
220
- it "freezes the cached object" do
221
- feature = SpecCustomerFeature.create(:feature_name => "Cancelled")
222
- expect(SpecCustomerFeature.aggregated_records_cache[feature.feature_name]).to be_frozen
223
- end
224
-
225
- it "caches the clone of the record, not the record itself" do
226
- feature = SpecCustomerFeature.create(:feature_name => "Returned")
227
- expect(SpecCustomerFeature.aggregated_records_cache[feature.feature_name].object_id).
228
- not_to eq feature.object_id
229
- end
144
+ it "has module included class check methods" do
145
+ expect(SpecCustomerFeature.acts_as_aggregated?).to be_truthy
146
+ expect(SpecCustomerEmail.acts_as_tracked?).to be_truthy
230
147
  end
231
148
  end
232
149
 
233
150
  describe "Tracked" do
234
151
  before do
235
152
  @customer = SpecCustomer.create
236
- @info = @customer.create_spec_customer_info :spec_person_name_id => 1
153
+ @info = @customer.create_spec_customer_info spec_person_name_id: 1
237
154
  end
238
155
 
239
156
  it "creates a new current record if updated" do
240
157
  expect {
241
- @info.update_attributes(:spec_person_name_id => 2)
158
+ @info.update_attributes(spec_person_name_id: 2)
242
159
  }.to change(SpecCustomerInfo, :count).by(1)
243
160
  end
244
161
 
245
162
  it "replaces itself with new id" do
246
163
  old_id = @info.id
247
- @info.update_attributes(:spec_person_name_id => 2)
164
+ @info.update_attributes(spec_person_name_id: 2)
248
165
  expect(@info.id).not_to eq old_id
249
166
  end
250
167
 
251
168
  it "sets is_current record to false for superseded record" do
252
169
  old_id = @info.id
253
- @info.update_attributes(:spec_person_name_id => 2)
170
+ @info.update_attributes(spec_person_name_id: 2)
254
171
  expect(SpecCustomerInfo.find(old_id).is_current).to eq false
255
172
  end
256
173
 
257
174
  it "sets previous_id to the id of the previous record" do
258
175
  old_id = @info.id
259
- @info.update_attributes(:spec_person_name_id => 2)
176
+ @info.update_attributes(spec_person_name_id: 2)
260
177
  expect(@info.previous_id).to eq old_id
261
178
  end
262
179
 
263
180
  it "changes is_current to false for previous one when assigning a new current record" do
264
- new_info = SpecCustomerInfo.new :spec_person_name_id => 2, :is_current => true
181
+ new_info = SpecCustomerInfo.new spec_person_name_id: 2, is_current: true
265
182
  @customer.spec_customer_info = new_info
266
183
  expect(new_info.spec_customer_id).to eq @customer.id
267
184
  @info.reload
@@ -269,12 +186,12 @@ describe Moribus do
269
186
  end
270
187
 
271
188
  it "does not crash on superseding with 'is_current' conditional constraint" do
272
- email = SpecCustomerEmail.create( :spec_customer => @customer,
273
- :email => "foo@bar.com",
274
- :status => "unverified",
275
- :is_current => true
189
+ email = SpecCustomerEmail.create( spec_customer: @customer,
190
+ email: "foo@bar.com",
191
+ status: "unverified",
192
+ is_current: true
276
193
  )
277
- expect{ email.update_attributes(:status => "verified") }.not_to raise_error
194
+ expect{ email.update_attributes(status: "verified") }.not_to raise_error
278
195
  end
279
196
 
280
197
  describe "updated_at and created_at" do
@@ -285,7 +202,7 @@ describe Moribus do
285
202
  after { Timecop.return }
286
203
 
287
204
  it "is updated on change" do
288
- info = @customer.create_spec_customer_info :spec_person_name_id => 1
205
+ info = @customer.create_spec_customer_info spec_person_name_id: 1
289
206
  expect(info.updated_at).to eq first_time
290
207
  expect(info.created_at).to eq first_time
291
208
 
@@ -304,9 +221,9 @@ describe Moribus do
304
221
  end
305
222
 
306
223
  it "raises a stale object error" do
307
- @info1.update_attributes(:spec_person_name_id => 3)
224
+ @info1.update_attributes(spec_person_name_id: 3)
308
225
 
309
- expect{ @info2.update_attributes(:spec_person_name_id => 4) }.
226
+ expect{ @info2.update_attributes(spec_person_name_id: 4) }.
310
227
  to raise_error(ActiveRecord::StaleObjectError,
311
228
  "Attempted to update_current (version #{@info2.lock_version}) a stale object: SpecCustomerInfo")
312
229
  end
@@ -315,17 +232,30 @@ describe Moribus do
315
232
  spec_customer_info = @customer.spec_customer_info
316
233
 
317
234
  expect {
318
- spec_customer_info.update_attributes(:spec_person_name_id => 3)
235
+ spec_customer_info.update_attributes(spec_person_name_id: 3)
319
236
  }.to change { spec_customer_info.lock_version }.from(0).to(1)
320
237
 
321
238
  expect {
322
- spec_customer_info.update_attributes(:spec_person_name_id => 4)
239
+ spec_customer_info.update_attributes(spec_person_name_id: 4)
323
240
  }.to change { spec_customer_info.lock_version }.from(1).to(2)
324
241
  end
325
242
 
243
+ it "does not fail to update if a lock version growth is for any reason not monotonic" do
244
+ spec_customer_info = @customer.spec_customer_info
245
+
246
+ spec_customer_info.update_attributes(spec_person_name_id: 3)
247
+ spec_customer_info.update_attributes(spec_person_name_id: 4)
248
+
249
+ SpecCustomerInfo.where(spec_customer_id: @customer.id, lock_version: 1).delete_all
250
+
251
+ expect {
252
+ spec_customer_info.update_attributes(spec_person_name_id: 5)
253
+ }.to change { spec_customer_info.lock_version }.from(2).to(3)
254
+ end
255
+
326
256
  it "does not fail if no locking_column is present" do
327
- email = SpecCustomerEmail.create(:spec_customer_id => 1, :email => "foo@bar.com")
328
- expect{ email.update_attributes(:email => "foo2@bar.com") }.not_to raise_error
257
+ email = SpecCustomerEmail.create(spec_customer_id: 1, email: "foo@bar.com")
258
+ expect{ email.update_attributes(email: "foo2@bar.com") }.not_to raise_error
329
259
  end
330
260
 
331
261
  it "updates lock_version column based on parent relation" do
@@ -333,29 +263,29 @@ describe Moribus do
333
263
  spec_customer_info = @customer.spec_customer_info
334
264
 
335
265
  expect {
336
- spec_customer_info.update_attributes(:spec_person_name_id => 3)
266
+ spec_customer_info.update_attributes(spec_person_name_id: 3)
337
267
  }.to change { spec_customer_info.lock_version }.from(0).to(1)
338
268
 
339
269
  expect {
340
- spec_customer_info.update_attributes(:spec_customer => @other_customer)
270
+ spec_customer_info.update_attributes(spec_customer: @other_customer)
341
271
  }.to change { spec_customer_info.lock_version }.from(1).to(0)
342
272
  end
343
273
 
344
274
  it "updates lock_version column base on relation list from 'by' option" do
345
275
  info_with_type =
346
- @customer.reload.create_spec_customer_info_with_type(:spec_type => :important)
276
+ @customer.reload.create_spec_customer_info_with_type(spec_type: :important)
347
277
 
348
278
  expect( info_with_type.lock_version ).to eq 0
349
279
 
350
280
  other_info_with_type =
351
- @customer.reload.create_spec_customer_info_with_type(:spec_type => :unimportant)
281
+ @customer.reload.create_spec_customer_info_with_type(spec_type: :unimportant)
352
282
 
353
283
  expect( other_info_with_type.lock_version ).to eq 0
354
284
 
355
- info_with_type.update_attributes(:spec_status => :active)
285
+ info_with_type.update_attributes(spec_status: :active)
356
286
  expect( info_with_type.lock_version ).to eq 1
357
287
 
358
- info_with_type.update_attributes(:spec_status => :inactive)
288
+ info_with_type.update_attributes(spec_status: :inactive)
359
289
  expect( info_with_type.lock_version ).to eq 2
360
290
 
361
291
  expect( other_info_with_type.lock_version ).to eq 0
@@ -365,7 +295,7 @@ describe Moribus do
365
295
  describe "with Aggregated" do
366
296
  before do
367
297
  @info.spec_person_name =
368
- SpecPersonName.create(:first_name => "John", :last_name => "Smith")
298
+ SpecPersonName.create(first_name: "John", last_name: "Smith")
369
299
  @info.save
370
300
  @info.reload
371
301
  end
@@ -374,59 +304,12 @@ describe Moribus do
374
304
  old_id = @info.id
375
305
  @customer.spec_customer_info.spec_person_name.first_name = "Alice"
376
306
  expect{ @customer.save }.to change(@info, :spec_person_name_id)
377
- expect(@info.id).not_to eq old_id
378
- expect(@info.is_current).to eq true
379
- expect(SpecCustomerInfo.find(old_id).is_current).to eq false
380
- end
381
- end
382
- end
383
-
384
- describe "Delegations" do
385
- before do
386
- @customer = SpecCustomer.create(
387
- :spec_customer_info_attributes => {
388
- :spec_person_name_attributes => {:first_name => " John ", :last_name => "Smith"} } )
389
- @info = @customer.spec_customer_info
390
- end
391
307
 
392
- it "has delegated column information" do
393
- expect(@customer.column_for_attribute(:first_name)).not_to be_nil
394
- end
395
-
396
- it "does not delegate special methods" do
397
- expect(@customer).not_to respond_to(:reset_first_name)
398
- expect(@customer).not_to respond_to(:first_name_was)
399
- expect(@customer).not_to respond_to(:first_name_before_type_cast)
400
- expect(@customer).not_to respond_to(:first_name_will_change!)
401
- expect(@customer).not_to respond_to(:first_name_changed?)
402
- expect(@customer).not_to respond_to(:lock_version)
403
- end
308
+ expect(@info.id ).not_to eq old_id
309
+ expect(@info.is_current).to eq true
404
310
 
405
- it "delegates methods to aggregated parts" do
406
- expect(@info).to respond_to(:first_name)
407
- expect(@info).to respond_to(:first_name=)
408
- expect(@info).to respond_to(:spec_suffix)
409
- expect(@info.last_name).to eq "Smith"
410
- end
411
-
412
- it "delegates methods to representation" do
413
- expect(@customer).to respond_to(:first_name)
414
- expect(@customer).to respond_to(:first_name=)
415
- expect(@customer).to respond_to(:spec_suffix)
416
- expect(@customer.last_name).to eq "Smith"
417
- expect(@customer).to respond_to(:custom_field)
418
- expect(@customer).to respond_to(:custom_field=)
419
- end
420
-
421
- it "properly delegates enumerated attributes" do
422
- expect(@customer).to respond_to(:spec_type)
423
- expect(@customer).to respond_to(:spec_type=)
424
- @customer.spec_type = :important
425
- expect(@customer.spec_type === :important).to eq true
426
- end
427
-
428
- it "raises NoMethodError if unknown method is received" do
429
- expect{ @customer.impossibru }.to raise_error(NoMethodError)
311
+ expect(SpecCustomerInfo.find(old_id).is_current).to eq false
312
+ end
430
313
  end
431
314
  end
432
315
  end
@@ -2,10 +2,12 @@
2
2
  module MoribusSpecModel
3
3
  def self.cleanup!
4
4
  ObjectSpace.each_object(MoribusSpecModel) do |klass|
5
- if Object.const_defined? klass.name.to_sym
6
- conn, table_name = klass.connection, klass.table_name
7
- conn.drop_table(table_name) if conn.tables.include?(table_name)
8
- Object.send :remove_const, klass.name.to_sym
5
+ unless klass.name.nil?
6
+ if Object.const_defined? klass.name.to_sym
7
+ conn, table_name = klass.connection, klass.table_name
8
+ conn.drop_table(table_name) if conn.tables.include?(table_name)
9
+ Object.send :remove_const, klass.name.to_sym
10
+ end
9
11
  end
10
12
  end
11
13
  ActiveSupport::Dependencies::Reference.clear!
data/tags CHANGED
@@ -27,12 +27,16 @@ HasAggregatedExtension lib/moribus/extensions/has_aggregated_extension.rb 5;" m
27
27
  HasCurrentExtension lib/moribus/extensions/has_current_extension.rb 5;" m line:5 class:Moribus.Extensions
28
28
  Helper lib/moribus/extensions/has_aggregated_extension.rb 18;" c line:18 class:Moribus.Extensions.HasAggregatedExtension
29
29
  K.D coverage/assets/0.10.0/application.js 17;" f line:17
30
+ K.D coverage/assets/0.10.2/application.js 17;" f line:17
30
31
  K.D coverage/assets/0.8.0/application.js 17;" f line:17
31
32
  K.E coverage/assets/0.10.0/application.js 17;" f line:17
33
+ K.E coverage/assets/0.10.2/application.js 17;" f line:17
32
34
  K.E coverage/assets/0.8.0/application.js 17;" f line:17
33
35
  K.l coverage/assets/0.10.0/application.js 17;" f line:17
36
+ K.l coverage/assets/0.10.2/application.js 17;" f line:17
34
37
  K.l coverage/assets/0.8.0/application.js 17;" f line:17
35
38
  K.m coverage/assets/0.10.0/application.js 17;" f line:17
39
+ K.m coverage/assets/0.10.2/application.js 17;" f line:17
36
40
  K.m coverage/assets/0.8.0/application.js 17;" f line:17
37
41
  Macros lib/moribus/macros.rb 4;" m line:4 class:Moribus
38
42
  Moribus lib/moribus.rb 6;" m line:6
@@ -46,23 +50,39 @@ Moribus lib/moribus/extensions/has_current_extension.rb 1;" m line:1
46
50
  Moribus lib/moribus/macros.rb 1;" m line:1
47
51
  Moribus lib/moribus/tracked_behavior.rb 1;" m line:1
48
52
  Moribus lib/moribus/version.rb 1;" m line:1
49
- MoribusSpecModel spec/support/moribus_spec_model.rb 26;" f line:26
53
+ MoribusSpecModel spec/support/moribus_spec_model.rb 28;" f line:28
50
54
  MoribusSpecModel spec/support/moribus_spec_model.rb 2;" m line:2
51
55
  SpecAuthor spec/moribus/alias_association_spec.rb 15;" c line:15
52
56
  SpecComment spec/moribus/alias_association_spec.rb 23;" c line:23
53
- SpecCustomer spec/moribus_spec.rb 87;" c line:87
54
- SpecCustomerEmail spec/moribus_spec.rb 95;" c line:95
55
- SpecCustomerFeature spec/moribus_spec.rb 44;" c line:44
56
- SpecCustomerInfo spec/moribus_spec.rb 48;" c line:48
57
- SpecCustomerInfoWithType spec/moribus_spec.rb 69;" c line:69
57
+ SpecCustomer spec/moribus/extensions/delegate_associated_spec.rb 66;" c line:66
58
+ SpecCustomer spec/moribus/extensions/has_current_extension_spec.rb 17;" c line:17
59
+ SpecCustomer spec/moribus/macros_spec.rb 7;" c line:7
60
+ SpecCustomer spec/moribus_spec.rb 88;" c line:88
61
+ SpecCustomerEmail spec/moribus_spec.rb 96;" c line:96
62
+ SpecCustomerFeature spec/moribus/aggregated_behavior_spec.rb 28;" c line:28
63
+ SpecCustomerFeature spec/moribus_spec.rb 45;" c line:45
64
+ SpecCustomerInfo spec/moribus/extensions/delegate_associated_spec.rb 45;" c line:45
65
+ SpecCustomerInfo spec/moribus/extensions/has_current_extension_spec.rb 5;" c line:5
66
+ SpecCustomerInfo spec/moribus/macros_spec.rb 12;" c line:12
67
+ SpecCustomerInfo spec/moribus_spec.rb 49;" c line:49
68
+ SpecCustomerInfoOrder spec/moribus/macros_spec.rb 29;" c line:29
69
+ SpecCustomerInfoWithType spec/moribus_spec.rb 70;" c line:70
70
+ SpecCustomerOrder spec/moribus/macros_spec.rb 24;" c line:24
71
+ SpecPersonName spec/moribus/aggregated_behavior_spec.rb 13;" c line:13
72
+ SpecPersonName spec/moribus/extensions/delegate_associated_spec.rb 29;" c line:29
58
73
  SpecPersonName spec/moribus_spec.rb 29;" c line:29
59
74
  SpecPost spec/moribus/alias_association_spec.rb 5;" c line:5
60
75
  SpecPostInfo spec/moribus/alias_association_spec.rb 19;" c line:19
76
+ SpecStatus spec/moribus/extensions/delegate_associated_spec.rb 5;" c line:5
61
77
  SpecStatus spec/moribus_spec.rb 5;" c line:5
78
+ SpecSuffix spec/moribus/aggregated_behavior_spec.rb 5;" c line:5
79
+ SpecSuffix spec/moribus/extensions/delegate_associated_spec.rb 21;" c line:21
62
80
  SpecSuffix spec/moribus_spec.rb 21;" c line:21
81
+ SpecType spec/moribus/extensions/delegate_associated_spec.rb 13;" c line:13
63
82
  SpecType spec/moribus_spec.rb 13;" c line:13
64
83
  TrackedBehavior lib/moribus/tracked_behavior.rb 8;" m line:8 class:Moribus
65
84
  V.N coverage/assets/0.10.0/application.js 17;" f line:17
85
+ V.N coverage/assets/0.10.2/application.js 17;" f line:17
66
86
  V.N coverage/assets/0.8.0/application.js 17;" f line:17
67
87
  acts_as_aggregated lib/moribus.rb 28;" f line:28 class:Moribus.ClassMethods
68
88
  acts_as_aggregated? lib/moribus.rb 58;" f line:58 class:Moribus.ClassMethods
@@ -77,27 +97,38 @@ alias_collection_association_methods lib/moribus/alias_association.rb 108;" f li
77
97
  alias_singular_association_methods lib/moribus/alias_association.rb 98;" f line:98 class:Moribus.AliasAssociation.ClassMethods
78
98
  association lib/moribus/extensions.rb 24;" f line:24 class:Moribus.Extensions
79
99
  b$.bA coverage/assets/0.10.0/application.js 17;" f line:17
100
+ b$.bA coverage/assets/0.10.2/application.js 17;" f line:17
80
101
  b$.bA coverage/assets/0.8.0/application.js 17;" f line:17
81
102
  b$.bW coverage/assets/0.10.0/application.js 17;" f line:17
103
+ b$.bW coverage/assets/0.10.2/application.js 17;" f line:17
82
104
  b$.bW coverage/assets/0.8.0/application.js 17;" f line:17
83
105
  b$.bX coverage/assets/0.10.0/application.js 17;" f line:17
106
+ b$.bX coverage/assets/0.10.2/application.js 17;" f line:17
84
107
  b$.bX coverage/assets/0.8.0/application.js 17;" f line:17
85
108
  b$.bY coverage/assets/0.10.0/application.js 17;" f line:17
109
+ b$.bY coverage/assets/0.10.2/application.js 17;" f line:17
86
110
  b$.bY coverage/assets/0.8.0/application.js 17;" f line:17
87
111
  b$.bZ coverage/assets/0.10.0/application.js 17;" f line:17
112
+ b$.bZ coverage/assets/0.10.2/application.js 17;" f line:17
88
113
  b$.bZ coverage/assets/0.8.0/application.js 17;" f line:17
89
114
  b$.bi coverage/assets/0.10.0/application.js 17;" f line:17
115
+ b$.bi coverage/assets/0.10.2/application.js 17;" f line:17
90
116
  b$.bi coverage/assets/0.8.0/application.js 17;" f line:17
91
117
  b$.bj coverage/assets/0.10.0/application.js 17;" f line:17
118
+ b$.bj coverage/assets/0.10.2/application.js 17;" f line:17
92
119
  b$.bj coverage/assets/0.8.0/application.js 17;" f line:17
93
120
  b$.bk coverage/assets/0.10.0/application.js 17;" f line:17
121
+ b$.bk coverage/assets/0.10.2/application.js 17;" f line:17
94
122
  b$.bk coverage/assets/0.8.0/application.js 17;" f line:17
95
123
  b$.bl coverage/assets/0.10.0/application.js 17;" f line:17
124
+ b$.bl coverage/assets/0.10.2/application.js 17;" f line:17
96
125
  b$.bl coverage/assets/0.8.0/application.js 17;" f line:17
97
126
  b$.bm coverage/assets/0.10.0/application.js 17;" f line:17
127
+ b$.bm coverage/assets/0.10.2/application.js 17;" f line:17
98
128
  b$.bm coverage/assets/0.8.0/application.js 17;" f line:17
99
129
  belongs_to lib/moribus/alias_association.rb 39;" f line:39 class:Moribus.AliasAssociation.ClassMethods
100
130
  bh.bg coverage/assets/0.10.0/application.js 17;" f line:17
131
+ bh.bg coverage/assets/0.10.2/application.js 17;" f line:17
101
132
  bh.bg coverage/assets/0.8.0/application.js 17;" f line:17
102
133
  bold lib/colorized_text.rb 30;" f line:30 class:ColorizedText
103
134
  cache_aggregated_record lib/moribus/aggregated_cache_behavior.rb 63;" f line:63 class:Moribus.AggregatedCacheBehavior
@@ -108,19 +139,24 @@ colorize lib/colorized_text.rb 10;" f line:10 class:ColorizedText
108
139
  column_for_attribute lib/moribus/extensions/delegate_associated.rb 35;" f line:35 class:Moribus.Extensions.DelegateAssociated
109
140
  content_changed? lib/moribus/tracked_behavior.rb 48;" f line:48 class:Moribus.TrackedBehavior
110
141
  cp.ce coverage/assets/0.10.0/application.js 17;" f line:17
142
+ cp.ce coverage/assets/0.10.2/application.js 17;" f line:17
111
143
  cp.ce coverage/assets/0.8.0/application.js 17;" f line:17
112
144
  cp.cf coverage/assets/0.10.0/application.js 17;" f line:17
145
+ cp.cf coverage/assets/0.10.2/application.js 17;" f line:17
113
146
  cp.cf coverage/assets/0.8.0/application.js 17;" f line:17
114
- current_lock_value lib/moribus/tracked_behavior.rb 132;" f line:132
115
- current_to_false_sql_statement lib/moribus/tracked_behavior.rb 105;" f line:105 class:Moribus.TrackedBehavior
147
+ current_lock_value lib/moribus/tracked_behavior.rb 144;" f line:144
148
+ current_to_false_sql_statement lib/moribus/tracked_behavior.rb 117;" f line:117 class:Moribus.TrackedBehavior
116
149
  define_delegation_module lib/moribus/extensions/has_aggregated_extension.rb 40;" f line:40 class:Moribus.Extensions.HasAggregatedExtension.Helper
117
150
  define_effective_reader_for lib/moribus/macros.rb 144;" f line:144 class:Moribus.Macros
118
151
  delegate_associated lib/moribus/macros.rb 51;" f line:51 class:Moribus.Macros
119
152
  effective_ lib/moribus/macros.rb 146;" f line:146 class:Moribus.Macros.define_effective_reader_for
120
153
  extend lib/moribus/extensions/has_aggregated_extension.rb 32;" f line:32 class:Moribus.Extensions.HasAggregatedExtension.Helper
121
154
  extend_has_aggregated_reflection lib/moribus/extensions.rb 16;" f line:16 class:Moribus.Extensions.ClassMethods
122
- first_name= spec/moribus_spec.rb 39;" f line:39 class:SpecPersonName
155
+ first_name= spec/moribus/aggregated_behavior_spec.rb 23;" f line:23 class:SpecPersonName
156
+ first_name= spec/moribus/extensions/delegate_associated_spec.rb 40;" f line:40 class:SpecPersonName
157
+ first_name= spec/moribus_spec.rb 40;" f line:40 class:SpecPersonName
123
158
  function.cr coverage/assets/0.10.0/application.js 17;" f line:17
159
+ function.cr coverage/assets/0.10.2/application.js 17;" f line:17
124
160
  function.cr coverage/assets/0.8.0/application.js 17;" f line:17
125
161
  get_parent_relation_keys lib/moribus.rb 71;" f line:71 class:Moribus.ClassMethods
126
162
  green lib/colorized_text.rb 20;" f line:20 class:ColorizedText
@@ -131,8 +167,10 @@ has_one_current lib/moribus/macros.rb 78;" f line:78 class:Moribus.Macros
131
167
  include_delegation_module lib/moribus/extensions/has_aggregated_extension.rb 81;" f line:81 class:Moribus.Extensions.HasAggregatedExtension.Helper
132
168
  initialize lib/moribus/extensions/has_aggregated_extension.rb 26;" f line:26 class:Moribus.Extensions.HasAggregatedExtension.Helper
133
169
  k.function.J coverage/assets/0.10.0/application.js 17;" f line:17
170
+ k.function.J coverage/assets/0.10.2/application.js 17;" f line:17
134
171
  k.function.J coverage/assets/0.8.0/application.js 17;" f line:17
135
172
  k.var.e coverage/assets/0.10.0/application.js 17;" f line:17
173
+ k.var.e coverage/assets/0.10.2/application.js 17;" f line:17
136
174
  k.var.e coverage/assets/0.8.0/application.js 17;" f line:17
137
175
  lookup_relation lib/moribus/aggregated_behavior.rb 72;" f line:72 class:Moribus.AggregatedBehavior
138
176
  lookup_self lib/moribus/aggregated_behavior.rb 65;" f line:65 class:Moribus.AggregatedBehavior
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.4
4
+ version: 0.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - HornsAndHooves
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2017-03-30 00:00:00.000000000 Z
14
+ date: 2018-11-29 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: rails
@@ -184,7 +184,10 @@ files:
184
184
  - spec/dummy/public/500.html
185
185
  - spec/dummy/public/favicon.ico
186
186
  - spec/dummy/script/rails
187
+ - spec/moribus/aggregated_behavior_spec.rb
187
188
  - spec/moribus/alias_association_spec.rb
189
+ - spec/moribus/extensions/delegate_associated_spec.rb
190
+ - spec/moribus/extensions/has_current_extension_spec.rb
188
191
  - spec/moribus/macros_spec.rb
189
192
  - spec/moribus_spec.rb
190
193
  - spec/spec_helper.rb
@@ -210,7 +213,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
210
213
  version: '0'
211
214
  requirements: []
212
215
  rubyforge_project:
213
- rubygems_version: 2.6.10
216
+ rubygems_version: 2.7.8
214
217
  signing_key:
215
218
  specification_version: 4
216
219
  summary: Introduces Aggregated and Tracked behavior to ActiveRecord::Base models
@@ -248,7 +251,10 @@ test_files:
248
251
  - spec/dummy/public/500.html
249
252
  - spec/dummy/public/favicon.ico
250
253
  - spec/dummy/script/rails
254
+ - spec/moribus/aggregated_behavior_spec.rb
251
255
  - spec/moribus/alias_association_spec.rb
256
+ - spec/moribus/extensions/delegate_associated_spec.rb
257
+ - spec/moribus/extensions/has_current_extension_spec.rb
252
258
  - spec/moribus/macros_spec.rb
253
259
  - spec/moribus_spec.rb
254
260
  - spec/spec_helper.rb