redundant_column 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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: ''
|