redundant_column 0.0.1 → 0.1.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.
- data/.gitignore +2 -0
- data/README.md +24 -2
- data/lib/redundant_column.rb +2 -33
- data/lib/redundant_column/belongs_to.rb +45 -0
- data/lib/redundant_column/has_many.rb +62 -0
- data/lib/redundant_column/version.rb +1 -1
- metadata +4 -2
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
# RedundantColumn
|
2
2
|
|
3
|
-
|
3
|
+
Auto maintain the consistency of redundant column.
|
4
|
+
|
5
|
+
1. Auto update redundant column.
|
6
|
+
2. Auto fill redundant column value from redundant target object.
|
4
7
|
|
5
8
|
## Installation
|
6
9
|
|
@@ -18,7 +21,26 @@ Or install it yourself as:
|
|
18
21
|
|
19
22
|
## Usage
|
20
23
|
|
21
|
-
|
24
|
+
class User < ActiveRecord::Base
|
25
|
+
has_many :topics, :redundant_column => {:status => :user_status}
|
26
|
+
end
|
27
|
+
|
28
|
+
class Topic < ActiveRecord::Base
|
29
|
+
belongs_to :user, :redundant_column => {:user_status => :status}
|
30
|
+
end
|
31
|
+
|
32
|
+
user = User.create(:name => "Hooopo", :status => "active")
|
33
|
+
|
34
|
+
topic = Topic.create(:user => user, :title => "this is title")
|
35
|
+
|
36
|
+
assert_equal topic.user_status, user.status
|
37
|
+
|
38
|
+
user.status = "disable"
|
39
|
+
user.save
|
40
|
+
|
41
|
+
topic.reload
|
42
|
+
|
43
|
+
assert_equal topic.user_status, user.status
|
22
44
|
|
23
45
|
## Contributing
|
24
46
|
|
data/lib/redundant_column.rb
CHANGED
@@ -1,34 +1,3 @@
|
|
1
1
|
require "redundant_column/version"
|
2
|
-
|
3
|
-
|
4
|
-
def redundant_column(name, target_model, options = {})
|
5
|
-
set_callback :update, :before, CallbackBuilder.new(name, target_model, options)
|
6
|
-
end
|
7
|
-
|
8
|
-
class CallbackBuilder
|
9
|
-
attr_reader :name, :target_model, :target_name, :association_name
|
10
|
-
|
11
|
-
def initialize(name, target_model, options = {})
|
12
|
-
@name = name
|
13
|
-
@target_model = target_model
|
14
|
-
@target_name = options[:target_name]
|
15
|
-
@association_name = options[:association_name] || "#{target_model.name.downcase.pluralize}"
|
16
|
-
end
|
17
|
-
|
18
|
-
def before_update(caller)
|
19
|
-
if caller.send("#{name}_changed?")
|
20
|
-
if caller.respond_to?(association_name)
|
21
|
-
new_column_value = caller.send(name)
|
22
|
-
target_name ||= "#{caller.class.name.downcase}_#{name}"
|
23
|
-
update_sql = new_column_value.is_a?(String) ? %Q|#{target_name} = '#{new_column_value.gsub("'", "\\'")}'| : %Q|#{target_name} = #{new_column_value}|
|
24
|
-
caller.send(association_name).update_all(update_sql)
|
25
|
-
else
|
26
|
-
STDERR.puts "You must set association in #{caller.class} model:"
|
27
|
-
STDERR.puts "has_many :#{association_name}, ..."
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
ActiveRecord::Base.send :extend, RedundantColumn
|
2
|
+
require 'redundant_column/has_many'
|
3
|
+
require 'redundant_column/belongs_to'
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module RedundantColumn
|
2
|
+
module BelongsTo
|
3
|
+
class CallbackBuilder
|
4
|
+
attr_reader :name, :target_name, :association_name
|
5
|
+
|
6
|
+
def initialize(name, target_name, association_name)
|
7
|
+
@name = name
|
8
|
+
@target_name = target_name
|
9
|
+
@association_name = association_name
|
10
|
+
end
|
11
|
+
|
12
|
+
def before_create(caller)
|
13
|
+
if caller.read_attribute(name).nil?
|
14
|
+
column_value = caller.send(association_name).try(target_name)
|
15
|
+
caller.send("#{name}=", column_value)
|
16
|
+
true
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.included(base)
|
22
|
+
base.valid_options += [:redundant_column]
|
23
|
+
end
|
24
|
+
|
25
|
+
def build
|
26
|
+
reflection = super
|
27
|
+
add_counter_cache_callbacks(reflection) if options[:counter_cache]
|
28
|
+
add_touch_callbacks(reflection) if options[:touch]
|
29
|
+
configure_dependency
|
30
|
+
configure_auto_fill_redundant_column_callback
|
31
|
+
reflection
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def configure_auto_fill_redundant_column_callback
|
37
|
+
if columns = options[:redundant_column]
|
38
|
+
column = columns.to_a.first
|
39
|
+
target_name = columns.to_a.last
|
40
|
+
model.set_callback :create, :before, CallbackBuilder.new(column, target_name, self.name)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
ActiveRecord::Associations::Builder::BelongsTo.send(:include, RedundantColumn::BelongsTo)
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module RedundantColumn
|
2
|
+
module HasMany
|
3
|
+
class CallbackBuilder
|
4
|
+
attr_reader :name, :target_name, :association_name
|
5
|
+
|
6
|
+
def initialize(name, target_name, association_name)
|
7
|
+
@name = name
|
8
|
+
@target_name = target_name
|
9
|
+
@association_name = association_name
|
10
|
+
end
|
11
|
+
|
12
|
+
def before_update(caller)
|
13
|
+
if caller.send("#{name}_changed?")
|
14
|
+
if caller.respond_to?(association_name)
|
15
|
+
new_column_value = caller.send(name)
|
16
|
+
|
17
|
+
update_sql = if new_column_value.is_a?(String)
|
18
|
+
%Q|#{target_name} = '#{new_column_value.gsub("'", "\\'")}'|
|
19
|
+
else
|
20
|
+
%Q|#{target_name} = #{new_column_value}|
|
21
|
+
end
|
22
|
+
caller.send(association_name).update_all(update_sql)
|
23
|
+
else
|
24
|
+
STDERR.puts "You must set association in #{caller.class} model:"
|
25
|
+
STDERR.puts "has_many :#{association_name}, ..."
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
def self.included(base)
|
33
|
+
base.valid_options += [:redundant_column]
|
34
|
+
end
|
35
|
+
|
36
|
+
def build
|
37
|
+
reflection = super
|
38
|
+
configure_dependency
|
39
|
+
configure_update_redundant_column_callback
|
40
|
+
reflection
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def configure_update_redundant_column_callback
|
46
|
+
if columns = options[:redundant_column]
|
47
|
+
if columns.is_a?(Array)
|
48
|
+
columns.each do |column|
|
49
|
+
model.set_callback :update, :before, CallbackBuilder.new(column, model.name.downcase + "_#{column}", self.name)
|
50
|
+
end
|
51
|
+
elsif columns.is_a?(Hash)
|
52
|
+
columns.each do |column, target_name|
|
53
|
+
model.set_callback :update, :before, CallbackBuilder.new(column, target_name, self.name)
|
54
|
+
end
|
55
|
+
else
|
56
|
+
model.set_callback :update, :before, CallbackBuilder.new(column, model.name.downcase + "_#{columns}", self.name)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
ActiveRecord::Associations::Builder::HasMany.send(:include, RedundantColumn::HasMany)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: redundant_column
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-07-
|
12
|
+
date: 2012-07-12 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: redundant column for activerecord
|
15
15
|
email:
|
@@ -24,6 +24,8 @@ files:
|
|
24
24
|
- README.md
|
25
25
|
- Rakefile
|
26
26
|
- lib/redundant_column.rb
|
27
|
+
- lib/redundant_column/belongs_to.rb
|
28
|
+
- lib/redundant_column/has_many.rb
|
27
29
|
- lib/redundant_column/version.rb
|
28
30
|
- redundant_column.gemspec
|
29
31
|
homepage: ''
|