ar-simple-idmap 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README +20 -2
- data/VERSION +1 -1
- data/lib/identity_map/active_record/base.rb +79 -79
- data/spec/identity_map_spec.rb +17 -0
- data/spec/spec_helper.rb +5 -0
- metadata +5 -6
- data/lib/identity_map/active_record/associations.rb +0 -31
data/README
CHANGED
@@ -42,18 +42,36 @@ Then you should enable identity map for each model class individually:
|
|
42
42
|
use_id_map
|
43
43
|
belongs_to :tarif_plan
|
44
44
|
end
|
45
|
+
|
46
|
+
You can use identity map for all models by writing in initializer:
|
47
|
+
|
48
|
+
class ActiveRecord::Base
|
49
|
+
use_id_map
|
50
|
+
end
|
45
51
|
|
46
52
|
To enable in rake task or script:
|
47
53
|
|
48
|
-
ActiveRecord.with_id_map do
|
54
|
+
ActiveRecord::Base.with_id_map do
|
49
55
|
# all things here goes with identity map
|
50
56
|
end
|
51
57
|
|
58
|
+
or equivalently
|
59
|
+
|
60
|
+
Client.with_id_map do
|
61
|
+
# all things here goes with identity map
|
62
|
+
# not only for Client
|
63
|
+
end
|
64
|
+
|
52
65
|
If you found that identity logic does wrong thing in some particular place,
|
53
66
|
you could temporary disable it:
|
54
67
|
|
55
|
-
ActiveRecord.without_id_map do
|
68
|
+
ActiveRecord::Base.without_id_map do
|
69
|
+
# all things here goes without identity map
|
70
|
+
end
|
71
|
+
|
72
|
+
Client.without_id_map do
|
56
73
|
# all things here goes without identity map
|
74
|
+
# not only for Client
|
57
75
|
end
|
58
76
|
|
59
77
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.2.
|
1
|
+
0.2.1
|
@@ -1,9 +1,9 @@
|
|
1
1
|
module ActiveRecord
|
2
2
|
class Base
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
module IdentityMap
|
4
|
+
module ClassMethods
|
5
|
+
private
|
6
|
+
def use_id_map
|
7
7
|
unless is_a? IdMapClassMethods
|
8
8
|
extend IdMapClassMethods
|
9
9
|
include IdMapInstanceMethods
|
@@ -14,21 +14,21 @@ module ActiveRecord
|
|
14
14
|
alias_method_chain :create, :identity_map
|
15
15
|
alias_method_chain :destroy, :identity_map
|
16
16
|
end
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
module IdMapClassMethods
|
21
21
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
22
|
+
def id_map
|
23
|
+
thread_id_map.try(:for_class, self)
|
24
|
+
end
|
25
|
+
|
26
|
+
def if_id_map
|
27
|
+
map = id_map
|
28
|
+
yield map if map
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
32
|
def fetch_from_map(map, ids)
|
33
33
|
result, not_cached = [], []
|
34
34
|
ids.each do |id|
|
@@ -44,9 +44,9 @@ module ActiveRecord
|
|
44
44
|
end
|
45
45
|
result
|
46
46
|
end
|
47
|
-
|
48
|
-
|
49
|
-
|
47
|
+
|
48
|
+
def find_with_identity_map( *args )
|
49
|
+
if_id_map do |map|
|
50
50
|
from_arg0 = args.size == 1 ||
|
51
51
|
args[1].is_a?(Hash) && !args[1].values.any?
|
52
52
|
from_condition_ids = !from_arg0 &&
|
@@ -55,11 +55,11 @@ module ActiveRecord
|
|
55
55
|
args[1].all?{|key, value| key == :conditions || value.blank?} &&
|
56
56
|
args[1][:conditions].is_a?(Hash) &&
|
57
57
|
args[1][:conditions].keys == [:id]
|
58
|
-
|
59
|
-
|
60
|
-
|
58
|
+
if from_arg0 || from_condition_ids
|
59
|
+
ids = from_arg0 ? args[0] : args[1][:conditions][:id]
|
60
|
+
if ids.is_a?(Array)
|
61
61
|
if from_arg0
|
62
|
-
|
62
|
+
fetch_from_map( map, ids, &method(:find_without_identity_map) )
|
63
63
|
elsif args[0] == :all
|
64
64
|
fetch_from_map( map, ids ){|not_cached|
|
65
65
|
find_without_identity_map(:all, {:conditions=>{:id=>not_cached}})
|
@@ -73,60 +73,60 @@ module ActiveRecord
|
|
73
73
|
find_without_identity_map(:first, {:conditions=>{:id=>to_find}})
|
74
74
|
end
|
75
75
|
end
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
76
|
+
else
|
77
|
+
map[ids]
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end || find_without_identity_map(*args)
|
81
|
+
end
|
82
|
+
|
83
|
+
def instantiate_with_identity_map( record )
|
84
|
+
if_id_map do |map|
|
85
|
+
id = record[primary_key]
|
86
|
+
if (object = map[id])
|
87
|
+
attrs = object.instance_variable_get( :@attributes )
|
88
|
+
unless (changed = object.instance_variable_get( :@changed_attributes )).blank?
|
89
|
+
for key, value in record
|
90
|
+
if changed.has_key? key
|
91
|
+
changed[key] = value
|
92
|
+
else
|
93
|
+
attrs[key] = value
|
94
|
+
end
|
95
|
+
end
|
96
|
+
else
|
97
|
+
attrs.merge!( record ) unless attrs == record
|
98
|
+
end
|
99
|
+
object
|
100
|
+
else
|
101
|
+
map[id] = instantiate_without_identity_map( record )
|
102
|
+
end
|
103
|
+
end || instantiate_without_identity_map( record )
|
104
|
+
end
|
105
|
+
|
106
|
+
def delete_with_identity_map( ids )
|
107
|
+
res = delete_without_identity_map( ids )
|
108
|
+
if_id_map{|map| [ *ids ].each{|id| map.delete(id) } }
|
109
|
+
res
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
module IdMapInstanceMethods
|
114
|
+
private
|
115
|
+
def create_with_identity_map
|
116
|
+
id = create_without_identity_map
|
117
|
+
self.class.if_id_map{|map| map[id] = self }
|
118
|
+
id
|
119
|
+
end
|
120
|
+
|
121
|
+
def destroy_with_identity_map
|
122
|
+
res = destroy_without_identity_map
|
123
|
+
self.class.if_id_map{|map| map.delete(id) }
|
124
|
+
res
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
extend IdentityMap::ClassMethods
|
130
130
|
end
|
131
131
|
end
|
132
132
|
|
data/spec/identity_map_spec.rb
CHANGED
@@ -52,6 +52,23 @@ describe "Customers" do
|
|
52
52
|
c2.should be_nil
|
53
53
|
end
|
54
54
|
|
55
|
+
it "should reload adequatly" do
|
56
|
+
Customer.connection.update_sql('update customers set value=2;')
|
57
|
+
@billy.reload
|
58
|
+
@billy.value.should == 2
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should leave changed columns" do
|
62
|
+
@billy.value = 3
|
63
|
+
b = Customer.find_by_name("billy")
|
64
|
+
b.value.should == 3
|
65
|
+
b.value_changed?.should be_true
|
66
|
+
b.changes.should == {'value'=>[1,3]}
|
67
|
+
Customer.connection.update_sql('update customers set value=2;')
|
68
|
+
b = Customer.find_by_name("billy")
|
69
|
+
b.changes.should == {'value'=>[2,3]}
|
70
|
+
end
|
71
|
+
|
55
72
|
after(:each) do
|
56
73
|
@billy.destroy unless @billy.destroyed?
|
57
74
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -3,6 +3,10 @@ require 'spec'
|
|
3
3
|
require 'active_support'
|
4
4
|
require 'active_support/test_case'
|
5
5
|
require 'active_record'
|
6
|
+
begin
|
7
|
+
require 'active_record/railtie'
|
8
|
+
rescue MissingSourceFile
|
9
|
+
end
|
6
10
|
require 'active_record/test_case'
|
7
11
|
require 'action_controller'
|
8
12
|
require 'action_view'
|
@@ -19,6 +23,7 @@ ActiveRecord::Schema.define(:version => 0) do
|
|
19
23
|
puts "Creating Schema"
|
20
24
|
create_table :customers, :force => true do |t|
|
21
25
|
t.string :name
|
26
|
+
t.integer :value, :default=>1
|
22
27
|
end
|
23
28
|
create_table :phone_numbers, :force => true do |t|
|
24
29
|
t.string :number
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ar-simple-idmap
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 21
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 2
|
9
|
-
-
|
10
|
-
version: 0.2.
|
9
|
+
- 1
|
10
|
+
version: 0.2.1
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Sokolov Yura aka funny_falcon
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-08-
|
18
|
+
date: 2010-08-05 00:00:00 +04:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -51,7 +51,6 @@ files:
|
|
51
51
|
- lib/autotest/discover.rb
|
52
52
|
- lib/identity_map.rb
|
53
53
|
- lib/identity_map/action_controller/dispatcher.rb
|
54
|
-
- lib/identity_map/active_record/associations.rb
|
55
54
|
- lib/identity_map/active_record/base.rb
|
56
55
|
- lib/identity_map/cache.rb
|
57
56
|
- spec/identity_map_spec.rb
|
@@ -92,5 +91,5 @@ signing_key:
|
|
92
91
|
specification_version: 3
|
93
92
|
summary: Simple identity map for ActiveRecord
|
94
93
|
test_files:
|
95
|
-
- spec/identity_map_spec.rb
|
96
94
|
- spec/spec_helper.rb
|
95
|
+
- spec/identity_map_spec.rb
|
@@ -1,31 +0,0 @@
|
|
1
|
-
module IdentityMap
|
2
|
-
|
3
|
-
def self.included(base)
|
4
|
-
base.extend(ClassMethods)
|
5
|
-
class << base
|
6
|
-
alias_method_chain :association_instance_set, :identity_map
|
7
|
-
end
|
8
|
-
end
|
9
|
-
|
10
|
-
module ClassMethods
|
11
|
-
|
12
|
-
private
|
13
|
-
|
14
|
-
# Set the specified association instance.
|
15
|
-
def association_instance_set_with_identity_map(name, association)
|
16
|
-
identity_map = Thread.current['identity_map']
|
17
|
-
unless identity_map
|
18
|
-
association_instance_set_without_identity_map("@#{name}", association)
|
19
|
-
else
|
20
|
-
association_instance_set_without_identity_map("@#{name}", identity_map.put(association))
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
|
25
|
-
end
|
26
|
-
|
27
|
-
end
|
28
|
-
|
29
|
-
if Object.const_defined?("ActiveRecord")
|
30
|
-
ActiveRecord::Associations.send :include, IdentityMap
|
31
|
-
end
|