ar-simple-idmap 0.2.0 → 0.2.1
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/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
|