activerecord-redundancy 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ea48053646bbb9a46bac56dbdfbb38421deba343
4
- data.tar.gz: d773a73fa5b34e872888e085d82b4f623de8b53e
3
+ metadata.gz: faa2836ac314098d90878058bf77c1260a99decc
4
+ data.tar.gz: b6494ce4bbfdaf61a9eb799ad9daf418eeb76483
5
5
  SHA512:
6
- metadata.gz: d23cb5550eff70b10fad7f3f57b6a97ca5e9e494d6b3695d40a1459696bce13d9223c19da9bdaa84aac380297fa25ba66530f70c9de346f232bf055210da997f
7
- data.tar.gz: 39d26a0d4e8a438ed0aecb02af153188a1762719c5d6fbd76a6a078281705d5409ae3fbf229a3db7fcaae0be0fe40247476a00910462ba89a6f7f5e231a66d64
6
+ metadata.gz: 078c06ecc0f44628b258e97c6ca3290f0ce209ad450e5f84eb2f419e62c8c387e93fb236727e77179e35880c34b9499733e5de3e4a1ece02b954e98a37df0d02
7
+ data.tar.gz: 2f0cb3ee7453469962e52b95104450a40cae0308616447f775237dea18bf875d6a51cb923a25982d0e9a16e31c608c3af5283d62d110309f25cab0367028c4db
data/lib/redundancy.rb CHANGED
@@ -1,73 +1,47 @@
1
- require 'redundancy/cache_column'
1
+ require 'redundancy/utils'
2
2
 
3
3
  module Redundancy
4
4
  extend ActiveSupport::Concern
5
5
 
6
6
  included do
7
- before_save :redundancy_update_cache_column_after_save
7
+ before_save :update_redundacies_before_save
8
+ after_save :update_redundacies_after_save
8
9
  end
9
10
 
10
11
  private
11
12
 
12
- def redundancy_update_cache_column_after_save
13
- self.class.cache_columns.each do |cache_column|
14
- cache_column.update_record(self)
13
+ def update_redundacies_before_save
14
+ self.class.redundacies.each do |redundancy|
15
+ redundancy.before_save(self)
15
16
  end
16
17
  end
17
18
 
18
- module ClassMethods
19
- def redundancy association, attribute, options = {}
20
- options.assert_valid_keys(:cache_column, :inverse_of)
21
-
22
- reflection = self.reflect_on_association(association)
23
- raise ArgumentError, "Unknown association :#{association}" unless reflection
24
- raise ArgumentError, "BelongsTo or HasOne reflection needed" unless
25
- [:has_one, :belongs_to].include? reflection.macro
26
-
27
- inverse_associations = options[:inverse_of]
28
- inverse_associations ||= [model_name.plural, model_name.singular].map(&:to_sym)
29
-
30
- inverse_association = Array.wrap(inverse_associations).find do |inverse_association|
31
- reflection.klass.reflect_on_association(inverse_association)
32
- end
33
-
34
- raise ArgumentError, "Could not find the inverse association for #{association} (#{inverse_associations.inspect} in #{reflection.klass})" unless inverse_association
35
-
36
- foreign_key = reflection.foreign_key
37
- cache_column = options[:cache_column] || :"#{association}_#{attribute}"
38
-
39
- local_klass = self
40
- remote_klass = reflection.klass
41
-
42
- case reflection.macro
43
- when :belongs_to
44
- local_klass.cache_columns << CacheColumn.new({
45
- source: { association: association, attribute: attribute },
46
- dist: { association: nil, attribute: cache_column },
47
- change_if: foreign_key, klass: local_klass
48
- })
49
-
50
- when :has_one
51
- remote_klass.cache_columns << CacheColumn.new({
52
- source: { association: nil, attribute: attribute },
53
- dist: { association: inverse_association, attribute: cache_column },
54
- change_if: foreign_key, nil_unless: foreign_key, klass: remote_klass,
55
- set_prev_nil: { klass: local_klass, attribute: foreign_key }
56
- })
57
-
58
- end
19
+ def update_redundacies_after_save
20
+ self.class.redundacies.each do |redundancy|
21
+ redundancy.after_save(self)
22
+ end
23
+ end
59
24
 
60
- remote_klass.cache_columns << CacheColumn.new({
61
- source: { association: nil, attribute: attribute },
62
- dist: { association: inverse_association, attribute: cache_column },
63
- change_if: attribute, klass: remote_klass, update: true
64
- })
25
+ def update_redundacies
26
+ self.class.redundacies.each do |redundancy|
27
+ redundancy.before_save(self)
28
+ redundancy.after_save(self)
29
+ end
30
+ end
65
31
 
32
+ module ClassMethods
33
+ def cache_column association, attribute, options = {}
34
+ options.assert_valid_keys(:cache_column, :inverse_of)
35
+ Utils.cache_column self, association, attribute, options
36
+ end
66
37
 
38
+ def cache_method association, attribute, options = {}
39
+ options.assert_valid_keys(:cache_column, :inverse_of)
40
+ Utils.cache_method self, association, attribute, options
67
41
  end
68
42
 
69
- def cache_columns
70
- @cache_columns ||= []
43
+ def redundacies
44
+ @redundacies ||= []
71
45
  end
72
46
 
73
47
  end
@@ -77,4 +51,4 @@ end
77
51
  # include in AR
78
52
  ActiveSupport.on_load(:active_record) do
79
53
  ActiveRecord::Base.send(:include, Redundancy)
80
- end
54
+ end
@@ -0,0 +1,88 @@
1
+ module Redundancy
2
+
3
+ class UpdateBase
4
+ attr_reader :options
5
+ attr_reader :source, :dest, :klass
6
+ attr_reader :change_if, :update, :target, :value
7
+
8
+ def initialize options
9
+ @options = options
10
+ @source, @dest = options[:source], options[:dest]
11
+ @klass = options[:klass]
12
+
13
+ @change_if = options[:change_if]
14
+ @update = options[:update] || false
15
+ end
16
+
17
+ def before_save record
18
+ end
19
+
20
+ def after_save record
21
+ end
22
+
23
+ def get_target_from_association record
24
+ @target = dest[:association] ? record.send(dest[:association]) : record
25
+ end
26
+
27
+ def get_target_from_prev_id record
28
+ prev_id = record.send(:attribute_was, dest[:prev_id])
29
+ return unless prev_id
30
+ @target = dest[:klass].where(id: prev_id)
31
+ end
32
+
33
+ def get_target_from_relation_first_record
34
+ @target = @target.first if @target.kind_of? ActiveRecord::Relation
35
+ end
36
+
37
+ def get_value_from_association record
38
+ @value = source[:association] ? record.send(source[:association]) : record
39
+ @value = value && source[:attribute] && value.send(source[:attribute])
40
+ @value = nil if source[:nil_unless] && !record.send(source[:nil_unless])
41
+ @value
42
+ end
43
+
44
+ def get_value_from_source record
45
+ @value = source
46
+ end
47
+
48
+ def get_value_from_target record
49
+ @value = target && source[:attribute] && target.send(source[:attribute])
50
+ end
51
+
52
+ def raise_if_class_mismatch record
53
+ raise ArgumentError, "record class mismatch, expected #{klass}, got #{record.class}" unless record.kind_of? klass
54
+ end
55
+
56
+ def update_target record
57
+ case target
58
+ when ActiveRecord::Base
59
+ return if target.send(:read_attribute, dest[:attribute]) == value
60
+ log "#{ update ? "update" : "write" } #{target.class}(#{target.id})##{dest[:attribute]} with #{value.inspect}"
61
+ log "#{change_if}: #{record.send(change_if).inspect}, #{dest[:association]||"self"}.id: #{target.id}" if change_if
62
+ if update
63
+ target.send(:update_attribute, dest[:attribute], value)
64
+ else
65
+ target.send(:write_attribute, dest[:attribute], value)
66
+ end
67
+ when ActiveRecord::Relation
68
+ log "update #{target.class}##{dest[:attribute]} with #{value.inspect}"
69
+ target.send(:update_all, dest[:attribute] => value)
70
+ end
71
+ end
72
+
73
+ def force_update_target record
74
+ @update = true
75
+ update_target record
76
+ end
77
+
78
+ def need_update? record
79
+ !change_if || record.send(:attribute_changed?, change_if)
80
+ end
81
+
82
+ def log *message
83
+ # puts *message
84
+ end
85
+
86
+ end
87
+
88
+ end
@@ -0,0 +1,19 @@
1
+ require 'redundancy/update_base'
2
+
3
+ module Redundancy
4
+
5
+ class UpdateColumn < UpdateBase
6
+
7
+ def before_save record
8
+ raise_if_class_mismatch record
9
+ return unless need_update? record
10
+
11
+ get_target_from_association record
12
+ get_value_from_association record
13
+
14
+ update_target record
15
+ end
16
+
17
+ end
18
+
19
+ end
@@ -0,0 +1,19 @@
1
+ require 'redundancy/update_base'
2
+
3
+ module Redundancy
4
+
5
+ class UpdateMethod < UpdateBase
6
+
7
+ def after_save record
8
+ raise_if_class_mismatch record
9
+ return unless need_update? record
10
+
11
+ get_target_from_association record
12
+ get_value_from_target record
13
+
14
+ force_update_target record
15
+ end
16
+
17
+ end
18
+
19
+ end
@@ -0,0 +1,19 @@
1
+ require 'redundancy/update_base'
2
+
3
+ module Redundancy
4
+
5
+ class UpdatePrevColumn < UpdateBase
6
+
7
+ def before_save record
8
+ raise_if_class_mismatch record
9
+ return unless need_update? record
10
+
11
+ get_target_from_prev_id record
12
+ get_value_from_source record
13
+
14
+ update_target record
15
+ end
16
+
17
+ end
18
+
19
+ end
@@ -0,0 +1,25 @@
1
+ require 'redundancy/update_base'
2
+
3
+ module Redundancy
4
+
5
+ class UpdatePrevMethod < UpdateBase
6
+
7
+ def before_save record
8
+ raise_if_class_mismatch record
9
+ return unless need_update? record
10
+
11
+ get_target_from_prev_id record
12
+ end
13
+
14
+ def after_save record
15
+ return unless need_update? record
16
+ return unless target
17
+
18
+ get_target_from_relation_first_record
19
+ get_value_from_target record
20
+ force_update_target record
21
+ end
22
+
23
+ end
24
+
25
+ end
@@ -0,0 +1,102 @@
1
+ require 'redundancy/update_column'
2
+ require 'redundancy/update_prev_column'
3
+ require 'redundancy/update_method'
4
+ require 'redundancy/update_prev_method'
5
+
6
+ module Redundancy
7
+
8
+ module Utils
9
+
10
+ def self.cache_column klass, association, attribute, options
11
+ local_klass = klass
12
+
13
+ reflection = get_reflection local_klass, association
14
+ raise ArgumentError, "BelongsTo or HasOne reflection required" unless
15
+ [:has_one, :belongs_to].include? reflection.macro
16
+
17
+ foreign_key = reflection.foreign_key
18
+ remote_klass = reflection.klass
19
+
20
+ inverse_association = get_inverse_association local_klass, remote_klass, options
21
+
22
+ cache_column = options[:cache_column] || :"#{association}_#{attribute}"
23
+
24
+ case reflection.macro
25
+ when :belongs_to
26
+ local_klass.redundacies << UpdateColumn.new(
27
+ source: { association: association, attribute: attribute },
28
+ dest: { association: nil, attribute: cache_column },
29
+ change_if: foreign_key, klass: local_klass
30
+ )
31
+
32
+ when :has_one
33
+ remote_klass.redundacies << UpdateColumn.new(
34
+ source: { association: nil, attribute: attribute, nil_unless: foreign_key },
35
+ dest: { association: inverse_association, attribute: cache_column },
36
+ change_if: foreign_key, klass: remote_klass
37
+ )
38
+
39
+ remote_klass.redundacies << UpdatePrevColumn.new(
40
+ source: options[:default],
41
+ dest: { klass: local_klass, prev_id: foreign_key, attribute: cache_column },
42
+ change_if: foreign_key, klass: remote_klass
43
+ )
44
+
45
+ end
46
+
47
+ remote_klass.redundacies << UpdateColumn.new(
48
+ source: { association: nil, attribute: attribute },
49
+ dest: { association: inverse_association, attribute: cache_column },
50
+ change_if: attribute, klass: remote_klass, update: true
51
+ )
52
+ end
53
+
54
+ def self.cache_method klass, association, attribute, options
55
+ local_klass = klass
56
+
57
+ reflection = get_reflection local_klass, association
58
+ raise ArgumentError, "BelongsTo reflection required" unless
59
+ [:belongs_to].include? reflection.macro
60
+
61
+ foreign_key = reflection.foreign_key
62
+ remote_klass = reflection.klass
63
+
64
+ cache_method = options[:cache_method] || :"raw_#{attribute}"
65
+
66
+ local_klass.redundacies << UpdateMethod.new(
67
+ source: { attribute: cache_method },
68
+ dest: { association: association, attribute: attribute },
69
+ change_if: options[:change_if], klass: local_klass
70
+ )
71
+
72
+ local_klass.redundacies << UpdatePrevMethod.new(
73
+ source: { attribute: cache_method },
74
+ dest: { klass: remote_klass, prev_id: foreign_key, attribute: attribute },
75
+ change_if: foreign_key, klass: local_klass
76
+ )
77
+
78
+ end
79
+
80
+ def self.get_reflection klass, association
81
+ reflection = klass.reflect_on_association(association)
82
+ raise ArgumentError, "Unknown association :#{association}" unless reflection
83
+ reflection
84
+ end
85
+
86
+ def self.get_inverse_association klass, reflection_klass, options
87
+ model_name = klass.model_name
88
+ inverse_associations = options[:inverse_of]
89
+ inverse_associations ||= [model_name.plural, model_name.singular].map(&:to_sym)
90
+
91
+ inverse_association = Array.wrap(inverse_associations).find do |inverse_association|
92
+ reflection_klass.reflect_on_association(inverse_association)
93
+ end
94
+
95
+ raise ArgumentError, "Could not find the inverse association for #{association} (#{inverse_associations.inspect} in #{reflection_klass})" unless inverse_association
96
+ inverse_association
97
+ end
98
+
99
+
100
+ end
101
+
102
+ end
@@ -1,3 +1,3 @@
1
1
  module Redundancy
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -21,6 +21,7 @@ class BelongsToHasOneAssociationTest < ActiveSupport::TestCase
21
21
 
22
22
  account.update_attribute(:user, user)
23
23
  assert_equal user.name, account.user_name
24
+ assert_equal user.name, account.reload.user_name
24
25
  end
25
26
 
26
27
  test "should update account.user_name when update account.user with nil" do
@@ -30,6 +31,7 @@ class BelongsToHasOneAssociationTest < ActiveSupport::TestCase
30
31
 
31
32
  account.update_attribute(:user, nil)
32
33
  assert_equal nil, account.user_name
34
+ assert_equal nil, account.reload.user_name
33
35
  end
34
36
 
35
37
  test "should update account.user_name when update account.user with other user" do
@@ -42,7 +44,8 @@ class BelongsToHasOneAssociationTest < ActiveSupport::TestCase
42
44
 
43
45
  account.update_attribute(:user, other_user)
44
46
  assert_equal other_user.name, account.user_name
45
- assert_equal nil, other_account.reload.user
47
+ assert_equal other_user.name, account.reload.user_name
48
+ assert_equal nil, other_account.user
46
49
  assert_equal nil, other_account.reload.user_name
47
50
  end
48
51
 
@@ -53,8 +56,7 @@ class BelongsToHasOneAssociationTest < ActiveSupport::TestCase
53
56
 
54
57
  user.update_attribute(:name, "Other Name")
55
58
  assert_equal user.name, user.account.user_name
56
-
57
59
  assert_equal user.name, account.reload.user_name
58
60
  end
59
61
 
60
- end
62
+ end
@@ -3,6 +3,7 @@ require 'test_helper'
3
3
  class HasManyBelongsToAssociationTest < ActiveSupport::TestCase
4
4
 
5
5
  # has_many:belongs_to association
6
+ # cache_column
6
7
  test "should update post.user_name when create post" do
7
8
  user = users(:one)
8
9
  post = Post.create(title: 'title', content: 'content', user: user)
@@ -21,6 +22,7 @@ class HasManyBelongsToAssociationTest < ActiveSupport::TestCase
21
22
 
22
23
  post.update_attribute(:user, user)
23
24
  assert_equal user.name, post.user_name
25
+ assert_equal user.name, post.reload.user_name
24
26
  end
25
27
 
26
28
  test "should update post.user_name when update post.user with nil" do
@@ -30,6 +32,7 @@ class HasManyBelongsToAssociationTest < ActiveSupport::TestCase
30
32
 
31
33
  post.update_attribute(:user, nil)
32
34
  assert_equal nil, post.user_name
35
+ assert_equal nil, post.reload.user_name
33
36
  end
34
37
 
35
38
  test "should update post.user_name when update post.user with other user" do
@@ -42,6 +45,7 @@ class HasManyBelongsToAssociationTest < ActiveSupport::TestCase
42
45
 
43
46
  post.update_attribute(:user, other_user)
44
47
  assert_equal other_user.name, post.user_name
48
+ assert_equal other_user.name, post.reload.user_name
45
49
  end
46
50
 
47
51
  test "should update post.user_name when update user.name" do
@@ -53,8 +57,6 @@ class HasManyBelongsToAssociationTest < ActiveSupport::TestCase
53
57
  user.posts.each do |post|
54
58
  assert_equal user.name, post.user_name
55
59
  end
56
-
57
60
  assert_equal user.name, post.reload.user_name
58
61
  end
59
-
60
62
  end
@@ -21,6 +21,7 @@ class HasOneBelongsToAssociationTest < ActiveSupport::TestCase
21
21
 
22
22
  user.update_attribute(:account, account)
23
23
  assert_equal account.email, user.account_email
24
+ assert_equal account.email, user.reload.account_email
24
25
  end
25
26
 
26
27
  test "should update user.account_email when update user.account with nil" do
@@ -30,6 +31,7 @@ class HasOneBelongsToAssociationTest < ActiveSupport::TestCase
30
31
 
31
32
  user.update_attribute(:account, nil)
32
33
  assert_equal nil, user.account_email
34
+ assert_equal nil, user.reload.account_email
33
35
  end
34
36
 
35
37
  test "should update user.account_email when update user.account with other account" do
@@ -42,8 +44,10 @@ class HasOneBelongsToAssociationTest < ActiveSupport::TestCase
42
44
 
43
45
  user.update_attribute(:account, other_account)
44
46
  assert_equal other_account.email, user.account_email
47
+ assert_equal other_account.email, user.reload.account_email
45
48
  assert_equal other_account, other_user.account
46
49
  assert_equal other_account.email, other_user.account_email
50
+ assert_equal other_account.email, other_user.reload.account_email
47
51
  end
48
52
 
49
53
  test "should update user.account_email when update account.email" do
@@ -57,4 +61,4 @@ class HasOneBelongsToAssociationTest < ActiveSupport::TestCase
57
61
  assert_equal account.email, user.reload.account_email
58
62
  end
59
63
 
60
- end
64
+ end
@@ -0,0 +1,70 @@
1
+ require 'test_helper'
2
+
3
+ class HasManyBelongsToAssociationTest < ActiveSupport::TestCase
4
+
5
+ # has_many:belongs_to association
6
+ # cache_method
7
+ test "should update user.posts_count when create post" do
8
+ user = users(:one)
9
+ post = Post.create(title: 'title', content: 'content', user: user)
10
+ assert_equal user.raw_posts_count, user.posts_count
11
+ end
12
+
13
+ test "should update user.posts_star when create post" do
14
+ user = users(:one)
15
+ post = Post.create(title: 'title', content: 'content', user: user, star: 5)
16
+ assert_equal user.raw_posts_star, user.posts_star
17
+ end
18
+
19
+ test "should update user.posts_star when create post without star" do
20
+ user = users(:one)
21
+ post = Post.create(title: 'title', content: 'content', user: user)
22
+ assert_equal user.raw_posts_star, user.posts_star
23
+ end
24
+
25
+ test "should update nothing when create post without user" do
26
+ post = Post.create(title: 'title', content: 'content')
27
+ end
28
+
29
+ test "should update user.posts_star when update post.user" do
30
+ user = users(:one)
31
+ post = posts(:two)
32
+ assert_equal user.raw_posts_star, user.posts_star
33
+
34
+ post.update_attribute(:user, user)
35
+ assert_equal user.raw_posts_star, user.reload.posts_star
36
+ end
37
+
38
+ test "should update user.posts_star when update post.user with nil" do
39
+ user = users(:one)
40
+ post = posts(:one)
41
+ assert_equal user.raw_posts_star, user.posts_star
42
+
43
+ post.update_attribute(:user, nil)
44
+ assert_equal user.raw_posts_star, user.reload.posts_star
45
+ end
46
+
47
+ test "should update user.posts_star when update post.user with other user" do
48
+ user = users(:one)
49
+ other_user = users(:two)
50
+ post = posts(:one)
51
+ other_post = posts(:two)
52
+ assert_equal user.raw_posts_star, user.posts_star
53
+ assert_equal other_user.raw_posts_star, other_user.posts_star
54
+
55
+ post.update_attribute(:user, other_user)
56
+ assert_equal user.raw_posts_star, user.reload.posts_star
57
+ assert_equal other_user.raw_posts_star, other_user.reload.posts_star
58
+ end
59
+
60
+ test "should update user.posts_star when update post.star" do
61
+ user = users(:one)
62
+ post = posts(:one)
63
+ assert_equal user.raw_posts_star, user.posts_star
64
+
65
+ post.update_attribute(:star, 5)
66
+ assert_equal user.raw_posts_star, post.user.posts_star
67
+ assert_equal user.raw_posts_star, user.reload.posts_star
68
+ end
69
+
70
+ end
@@ -7,6 +7,7 @@ one:
7
7
  user_id: 1
8
8
  user_name: Name 1
9
9
  username: Name 1
10
+ star: 3
10
11
 
11
12
  two:
12
13
  id: 2
@@ -15,3 +16,4 @@ two:
15
16
  user_id: 2
16
17
  user_name: Name 2
17
18
  username: Name 2
19
+ star: 5
@@ -5,9 +5,11 @@ one:
5
5
  name: Name 1
6
6
  account_id: 1
7
7
  account_email: one@one.com
8
+ posts_star: 3
8
9
 
9
10
  two:
10
11
  id: 2
11
12
  name: Name 2
12
13
  account_id: 2
13
14
  account_email: two@two.com
15
+ posts_star: 5
@@ -22,6 +22,7 @@ ActiveRecord::Schema.define do
22
22
  t.integer "user_id"
23
23
  t.string "user_name"
24
24
  t.string "username"
25
+ t.integer "star"
25
26
  t.string "title"
26
27
  t.text "content"
27
28
  t.datetime "created_at"
@@ -33,6 +34,8 @@ ActiveRecord::Schema.define do
33
34
  create_table "users", force: true do |t|
34
35
  t.integer "account_id"
35
36
  t.string "account_email"
37
+ t.integer "posts_count"
38
+ t.integer "posts_star"
36
39
  t.string "name"
37
40
  t.datetime "created_at"
38
41
  t.datetime "updated_at"
@@ -1,5 +1,5 @@
1
1
  class Account < ActiveRecord::Base
2
2
  has_one :user
3
-
4
- redundancy :user, :name
3
+
4
+ cache_column :user, :name
5
5
  end
@@ -1,6 +1,9 @@
1
1
  class Post < ActiveRecord::Base
2
2
  belongs_to :user
3
3
 
4
- redundancy :user, :name
5
- redundancy :user, :name, cache_column: :username
4
+ cache_column :user, :name
5
+ cache_column :user, :name, cache_column: :username
6
+
7
+ cache_method :user, :posts_count
8
+ cache_method :user, :posts_star
6
9
  end
@@ -2,5 +2,13 @@ class User < ActiveRecord::Base
2
2
  has_many :posts
3
3
  belongs_to :account
4
4
 
5
- redundancy :account, :email
5
+ cache_column :account, :email
6
+
7
+ def raw_posts_count
8
+ posts.count
9
+ end
10
+
11
+ def raw_posts_star
12
+ posts.average(:star)
13
+ end
6
14
  end
data/test/test_helper.rb CHANGED
@@ -20,3 +20,5 @@ ActiveSupport::TestCase.fixture_path = File.expand_path("../fixtures", __FILE__)
20
20
  class ActiveSupport::TestCase
21
21
  fixtures :all
22
22
  end
23
+
24
+ ActiveSupport.test_order = :sorted
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord-redundancy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Theo
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-07-18 00:00:00.000000000 Z
11
+ date: 2015-12-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -58,6 +58,20 @@ dependencies:
58
58
  - - ">="
59
59
  - !ruby/object:Gem::Version
60
60
  version: '0'
61
+ - !ruby/object:Gem::Dependency
62
+ name: pry-stack_explorer
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
61
75
  - !ruby/object:Gem::Dependency
62
76
  name: rails
63
77
  requirement: !ruby/object:Gem::Requirement
@@ -83,15 +97,21 @@ files:
83
97
  - Rakefile
84
98
  - lib/activerecord-redundancy.rb
85
99
  - lib/redundancy.rb
86
- - lib/redundancy/cache_column.rb
100
+ - lib/redundancy/update_base.rb
101
+ - lib/redundancy/update_column.rb
102
+ - lib/redundancy/update_method.rb
103
+ - lib/redundancy/update_prev_column.rb
104
+ - lib/redundancy/update_prev_method.rb
105
+ - lib/redundancy/utils.rb
87
106
  - lib/redundancy/version.rb
88
- - test/belongs_to_has_one_association_test.rb
107
+ - test/cache_column/belongs_to_has_one_association_test.rb
108
+ - test/cache_column/has_many_belongs_to_association_test.rb
109
+ - test/cache_column/has_one_belongs_to_association_test.rb
110
+ - test/cache_column/options_test.rb
111
+ - test/cache_method/has_many_belongs_to_association_test.rb
89
112
  - test/fixtures/accounts.yml
90
113
  - test/fixtures/posts.yml
91
114
  - test/fixtures/users.yml
92
- - test/has_many_belongs_to_association_test.rb
93
- - test/has_one_belongs_to_association_test.rb
94
- - test/options_test.rb
95
115
  - test/support/environment.rb
96
116
  - test/support/models/account.rb
97
117
  - test/support/models/post.rb
@@ -117,18 +137,19 @@ required_rubygems_version: !ruby/object:Gem::Requirement
117
137
  version: '0'
118
138
  requirements: []
119
139
  rubyforge_project:
120
- rubygems_version: 2.2.2
140
+ rubygems_version: 2.4.6
121
141
  signing_key:
122
142
  specification_version: 4
123
143
  summary: Redundancy for better performance, non painful
124
144
  test_files:
125
- - test/belongs_to_has_one_association_test.rb
145
+ - test/cache_column/belongs_to_has_one_association_test.rb
146
+ - test/cache_column/has_many_belongs_to_association_test.rb
147
+ - test/cache_column/has_one_belongs_to_association_test.rb
148
+ - test/cache_column/options_test.rb
149
+ - test/cache_method/has_many_belongs_to_association_test.rb
126
150
  - test/fixtures/accounts.yml
127
151
  - test/fixtures/posts.yml
128
152
  - test/fixtures/users.yml
129
- - test/has_many_belongs_to_association_test.rb
130
- - test/has_one_belongs_to_association_test.rb
131
- - test/options_test.rb
132
153
  - test/support/environment.rb
133
154
  - test/support/models/account.rb
134
155
  - test/support/models/post.rb
@@ -1,59 +0,0 @@
1
- module Redundancy
2
-
3
- class CacheColumn
4
- attr_reader :options
5
- attr_reader :source, :dist, :klass
6
- attr_reader :change_if, :nil_unless, :update, :set_prev_nil
7
-
8
- def initialize options
9
- @options = options
10
- @source, @dist = options[:source], options[:dist]
11
- @klass = options[:klass]
12
-
13
- @change_if = options[:change_if]
14
- @nil_unless = options[:nil_unless]
15
- @update = options[:update] || false
16
- @set_prev_nil = options[:set_prev_nil]
17
- end
18
-
19
- def update_record record
20
- raise ArgumentError, "record class mismatch, expected #{klass}, got #{record.class}" unless record.kind_of? klass
21
- return unless need_update?(record)
22
-
23
- src = source[:association] ? record.send(source[:association]) : record
24
- src = src && source[:attribute] && src.send(source[:attribute])
25
- src = nil if nil_unless && !record.send(nil_unless)
26
-
27
- dst = dist[:association] ? record.send(dist[:association]) : record
28
-
29
- set_prev_nil[:klass].where(id: record.send(:attribute_was, set_prev_nil[:attribute]))
30
- .update_all(dist[:attribute] => nil) if set_prev_nil
31
-
32
- case dst
33
- when ActiveRecord::Base
34
- return if dst.send(:read_attribute, dist[:attribute]) == src
35
- log "#{ update ? "update" : "write" } #{dst.class}(#{dst.id})##{dist[:attribute]} with #{src.inspect}"
36
- log "#{change_if}: #{record.send(change_if).inspect}, #{dist[:association]||"self"}.id: #{dst.id}"
37
- if update
38
- dst.send(:update_attribute, dist[:attribute], src)
39
- else
40
- dst.send(:write_attribute, dist[:attribute], src)
41
- end
42
- when ActiveRecord::Relation
43
- log "update #{dst.class}##{dist[:attribute]} with #{src.inspect}"
44
- dst.send(:update_all, dist[:attribute] => src)
45
- end
46
-
47
- end
48
-
49
- def need_update? record
50
- record.send(:attribute_changed?, change_if)
51
- end
52
-
53
- def log *message
54
- # puts *message
55
- end
56
-
57
- end
58
-
59
- end