active_hash 1.0.2 → 1.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 +9 -9
- data/CHANGELOG +4 -0
- data/lib/active_hash/version.rb +1 -1
- data/lib/associations/associations.rb +23 -9
- data/spec/associations/associations_spec.rb +138 -27
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
MTE0YzI0ZDYzNTQ0OTVmOTI1Zjk4MmZlZWZlNGNlNGVmZjEyMzAxMg==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
7
|
-
|
6
|
+
YTQwOGViNjkwZWJlOTkzZWZiZDgxNGU0NDgwZDVkNzE4OWY2MTE5Nw==
|
7
|
+
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
Y2U2MGUzZjdkZDg3ODYyM2Q1NDNmODgyNTY0YjM0N2U2ZTYyOGIzZmFlYWMz
|
10
|
+
MTBmNjBjMTVjZDFhMzU4M2Q5ODcxMmI4NzYxMGNlNWNiNTg2MjZhNGQ1MmZk
|
11
|
+
MmRhYTI0OWIzMzliNWFkN2E3ZjRmMDhmNmViNzg1ZTNlYjZjYjE=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
MTU4NzNmZjdiNzM1MzkyYjA4MTMxOTJjZjhkMzJhNTQ4MTMzYTQ5NGFkOWI1
|
14
|
+
YjRmYzRlZmRhMWRmYzQ1OWY0ZjY1ZWY4NGUyZDZmMjEwNGIwMzNjZjMzZTJl
|
15
|
+
NjhjMzZlNTFkOTA2MDU4YjQwZTMwN2U0ODhjNTY3NWM2ZWIwZmM=
|
data/CHANGELOG
CHANGED
data/lib/active_hash/version.rb
CHANGED
@@ -3,20 +3,31 @@ module ActiveHash
|
|
3
3
|
|
4
4
|
module ActiveRecordExtensions
|
5
5
|
|
6
|
+
def belongs_to(name, options = {})
|
7
|
+
options = {:class_name => name.to_s.camelize }.merge(options)
|
8
|
+
klass = options[:class_name].constantize
|
9
|
+
if klass < ActiveHash::Base
|
10
|
+
belongs_to_active_hash(name, options)
|
11
|
+
else
|
12
|
+
super
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
6
16
|
def belongs_to_active_hash(association_id, options = {})
|
7
17
|
options = {
|
8
18
|
:class_name => association_id.to_s.camelize,
|
9
19
|
:foreign_key => association_id.to_s.foreign_key,
|
20
|
+
:primary_key => association_id.to_s.camelize.constantize.primary_key,
|
10
21
|
:shortcuts => []
|
11
22
|
}.merge(options)
|
12
23
|
options[:shortcuts] = [options[:shortcuts]] unless options[:shortcuts].kind_of?(Array)
|
13
24
|
|
14
25
|
define_method(association_id) do
|
15
|
-
options[:class_name].constantize.
|
26
|
+
options[:class_name].constantize.send("find_by_#{options[:primary_key]}", send(options[:foreign_key]))
|
16
27
|
end
|
17
28
|
|
18
29
|
define_method("#{association_id}=") do |new_value|
|
19
|
-
send "#{options[:foreign_key]}=", new_value ? new_value.
|
30
|
+
send "#{options[:foreign_key]}=", new_value ? new_value.send(options[:primary_key]) : nil
|
20
31
|
end
|
21
32
|
|
22
33
|
options[:shortcuts].each do |shortcut|
|
@@ -60,17 +71,19 @@ module ActiveHash
|
|
60
71
|
define_method(association_id) do
|
61
72
|
options = {
|
62
73
|
:class_name => association_id.to_s.classify,
|
63
|
-
:foreign_key => self.class.to_s.foreign_key
|
74
|
+
:foreign_key => self.class.to_s.foreign_key,
|
75
|
+
:primary_key => self.class.primary_key
|
64
76
|
}.merge(options)
|
65
77
|
|
66
78
|
klass = options[:class_name].constantize
|
79
|
+
primary_key_value = send(options[:primary_key])
|
67
80
|
|
68
81
|
if ActiveRecord.const_defined?(:Relation) && klass.all.class < ActiveRecord::Relation
|
69
|
-
klass.where(options[:foreign_key] =>
|
82
|
+
klass.where(options[:foreign_key] => primary_key_value)
|
70
83
|
elsif klass.respond_to?(:scoped)
|
71
|
-
klass.scoped(:conditions => {options[:foreign_key] =>
|
84
|
+
klass.scoped(:conditions => {options[:foreign_key] => primary_key_value})
|
72
85
|
else
|
73
|
-
klass.send("find_all_by_#{options[:foreign_key]}",
|
86
|
+
klass.send("find_all_by_#{options[:foreign_key]}", primary_key_value)
|
74
87
|
end
|
75
88
|
end
|
76
89
|
end
|
@@ -95,17 +108,18 @@ module ActiveHash
|
|
95
108
|
|
96
109
|
options = {
|
97
110
|
:class_name => association_id.to_s.classify,
|
98
|
-
:foreign_key => association_id.to_s.foreign_key
|
111
|
+
:foreign_key => association_id.to_s.foreign_key,
|
112
|
+
:primary_key => "id"
|
99
113
|
}.merge(options)
|
100
114
|
|
101
115
|
field options[:foreign_key].to_sym
|
102
116
|
|
103
117
|
define_method(association_id) do
|
104
|
-
options[:class_name].constantize.
|
118
|
+
options[:class_name].constantize.send("find_by_#{options[:primary_key]}", send(options[:foreign_key]))
|
105
119
|
end
|
106
120
|
|
107
121
|
define_method("#{association_id}=") do |new_value|
|
108
|
-
attributes[options[:foreign_key].to_sym] = new_value ? new_value.
|
122
|
+
attributes[options[:foreign_key].to_sym] = new_value ? new_value.send(options[:primary_key]) : nil
|
109
123
|
end
|
110
124
|
|
111
125
|
end
|
@@ -5,19 +5,20 @@ describe ActiveHash::Base, "associations" do
|
|
5
5
|
|
6
6
|
before do
|
7
7
|
class Country < ActiveRecord::Base
|
8
|
-
extend ActiveHash::Associations::ActiveRecordExtensions
|
9
8
|
establish_connection :adapter => "sqlite3", :database => ":memory:"
|
10
9
|
connection.create_table(:countries, :force => true) do |t|
|
11
10
|
t.string :name
|
12
11
|
end
|
12
|
+
extend ActiveHash::Associations::ActiveRecordExtensions
|
13
13
|
end
|
14
14
|
|
15
15
|
class School < ActiveRecord::Base
|
16
|
-
extend ActiveHash::Associations::ActiveRecordExtensions
|
17
16
|
establish_connection :adapter => "sqlite3", :database => ":memory:"
|
18
17
|
connection.create_table(:schools, :force => true) do |t|
|
18
|
+
t.integer :country_id
|
19
19
|
t.integer :city_id
|
20
20
|
end
|
21
|
+
extend ActiveHash::Associations::ActiveRecordExtensions
|
21
22
|
end
|
22
23
|
|
23
24
|
class City < ActiveHash::Base
|
@@ -35,6 +36,7 @@ describe ActiveHash::Base, "associations" do
|
|
35
36
|
establish_connection :adapter => "sqlite3", :database => ":memory:"
|
36
37
|
connection.create_table(:books, :force => true) do |t|
|
37
38
|
t.integer :author_id
|
39
|
+
t.integer :author_code
|
38
40
|
t.boolean :published
|
39
41
|
end
|
40
42
|
|
@@ -57,43 +59,117 @@ describe ActiveHash::Base, "associations" do
|
|
57
59
|
describe "#has_many" do
|
58
60
|
|
59
61
|
context "with ActiveRecord children" do
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
62
|
+
context "with default options" do
|
63
|
+
before do
|
64
|
+
@book_1 = Book.create! :author_id => 1, :published => true
|
65
|
+
@book_2 = Book.create! :author_id => 1, :published => false
|
66
|
+
@book_3 = Book.create! :author_id => 2, :published => true
|
67
|
+
Author.has_many :books
|
68
|
+
end
|
69
|
+
|
70
|
+
it "find the correct records" do
|
71
|
+
author = Author.create :id => 1
|
72
|
+
author.books.should == [@book_1, @book_2]
|
73
|
+
end
|
74
|
+
|
75
|
+
it "return a scope so that we can apply further scopes" do
|
76
|
+
author = Author.create :id => 1
|
77
|
+
author.books.published.should == [@book_1]
|
78
|
+
end
|
64
79
|
end
|
65
80
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
81
|
+
context "with a primary_key option" do
|
82
|
+
before do
|
83
|
+
@book_1 = Book.create! :author_id => 1, :published => true
|
84
|
+
@book_2 = Book.create! :author_id => 2, :published => false
|
85
|
+
@book_3 = Book.create! :author_id => 2, :published => true
|
86
|
+
Author.field :book_identifier
|
87
|
+
Author.has_many :books, :primary_key => :book_identifier
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should find the correct records" do
|
91
|
+
author = Author.create :id => 1, :book_identifier => 2
|
92
|
+
author.books.should == [@book_2, @book_3]
|
93
|
+
end
|
94
|
+
|
95
|
+
it "return a scope so that we can apply further scopes" do
|
96
|
+
author = Author.create :id => 1, :book_identifier => 2
|
97
|
+
author.books.published.should == [@book_3]
|
98
|
+
end
|
70
99
|
end
|
71
100
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
101
|
+
context "with a foreign_key option" do
|
102
|
+
before do
|
103
|
+
@book_1 = Book.create! :author_code => 1, :published => true
|
104
|
+
@book_2 = Book.create! :author_code => 1, :published => false
|
105
|
+
@book_3 = Book.create! :author_code => 2, :published => true
|
106
|
+
Author.has_many :books, :foreign_key => :author_code
|
107
|
+
end
|
108
|
+
|
109
|
+
it "should find the correct records" do
|
110
|
+
author = Author.create :id => 1
|
111
|
+
author.books.should == [@book_1, @book_2]
|
112
|
+
end
|
113
|
+
|
114
|
+
it "return a scope so that we can apply further scopes" do
|
115
|
+
author = Author.create :id => 1
|
116
|
+
author.books.published.should == [@book_1]
|
117
|
+
end
|
76
118
|
end
|
77
119
|
end
|
78
120
|
|
79
121
|
context "with ActiveHash children" do
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
122
|
+
context "with default options" do
|
123
|
+
before do
|
124
|
+
Author.field :city_id
|
125
|
+
@included_author_1 = Author.create :city_id => 1
|
126
|
+
@included_author_2 = Author.create :city_id => 1
|
127
|
+
@excluded_author = Author.create :city_id => 2
|
128
|
+
end
|
129
|
+
|
130
|
+
it "find the correct records" do
|
131
|
+
City.has_many :authors
|
132
|
+
city = City.create :id => 1
|
133
|
+
city.authors.should == [@included_author_1, @included_author_2]
|
134
|
+
end
|
135
|
+
|
136
|
+
it "uses the correct class name when passed" do
|
137
|
+
City.has_many :writers, :class_name => "Author"
|
138
|
+
city = City.create :id => 1
|
139
|
+
city.writers.should == [@included_author_1, @included_author_2]
|
140
|
+
end
|
85
141
|
end
|
86
142
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
143
|
+
context "with a primary_key option" do
|
144
|
+
before do
|
145
|
+
Author.field :city_id
|
146
|
+
City.field :author_identifier
|
147
|
+
@author_1 = Author.create :city_id => 1
|
148
|
+
@author_2 = Author.create :city_id => 10
|
149
|
+
@author_3 = Author.create :city_id => 10
|
150
|
+
City.has_many :authors, :primary_key => :author_identifier
|
151
|
+
end
|
152
|
+
|
153
|
+
it "finds the correct records" do
|
154
|
+
city = City.create :id => 1, :author_identifier => 10
|
155
|
+
city.authors.should == [@author_2, @author_3]
|
156
|
+
end
|
91
157
|
end
|
92
158
|
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
159
|
+
context "with a foreign_key option" do
|
160
|
+
before do
|
161
|
+
Author.field :city_id
|
162
|
+
Author.field :city_identifier
|
163
|
+
@author_1 = Author.create :city_id => 1, :city_identifier => 10
|
164
|
+
@author_2 = Author.create :city_id => 10, :city_identifier => 10
|
165
|
+
@author_3 = Author.create :city_id => 10, :city_identifier => 5
|
166
|
+
City.has_many :authors, :foreign_key => :city_identifier
|
167
|
+
end
|
168
|
+
|
169
|
+
it "finds the correct records" do
|
170
|
+
city = City.create :id => 10
|
171
|
+
city.authors.should == [@author_1, @author_2]
|
172
|
+
end
|
97
173
|
end
|
98
174
|
end
|
99
175
|
|
@@ -101,6 +177,27 @@ describe ActiveHash::Base, "associations" do
|
|
101
177
|
|
102
178
|
describe ActiveHash::Associations::ActiveRecordExtensions do
|
103
179
|
|
180
|
+
describe "#belongs_to" do
|
181
|
+
it "sets up an ActiveRecord association for non-ActiveHash objects" do
|
182
|
+
School.belongs_to :country
|
183
|
+
school = School.new
|
184
|
+
country = Country.create!
|
185
|
+
school.country = country
|
186
|
+
school.country.should == country
|
187
|
+
school.country_id.should == country.id
|
188
|
+
school.save!
|
189
|
+
school.reload
|
190
|
+
school.reload.country_id.should == country.id
|
191
|
+
end
|
192
|
+
|
193
|
+
it "calls through to belongs_to_active_hash if it's an ActiveHash object" do
|
194
|
+
School.belongs_to :city
|
195
|
+
city = City.create
|
196
|
+
school = School.create :city_id => city.id
|
197
|
+
school.city.should == city
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
104
201
|
describe "#belongs_to_active_hash" do
|
105
202
|
context "setting by id" do
|
106
203
|
it "finds the correct records" do
|
@@ -239,6 +336,20 @@ describe ActiveHash::Base, "associations" do
|
|
239
336
|
author.city_id.should == @city.id
|
240
337
|
end
|
241
338
|
end
|
339
|
+
|
340
|
+
describe "with a different primary key" do
|
341
|
+
before do
|
342
|
+
City.field :long_identifier
|
343
|
+
Author.belongs_to :city, :primary_key => "long_identifier"
|
344
|
+
@city = City.create :id => 1, :long_identifier => "123"
|
345
|
+
end
|
346
|
+
|
347
|
+
it "works" do
|
348
|
+
author = Author.new
|
349
|
+
author.city = @city
|
350
|
+
author.city_id.should == @city.long_identifier
|
351
|
+
end
|
352
|
+
end
|
242
353
|
end
|
243
354
|
|
244
355
|
describe "#has_one" do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_hash
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeff Dean
|
@@ -148,7 +148,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
148
148
|
version: '0'
|
149
149
|
requirements: []
|
150
150
|
rubyforge_project:
|
151
|
-
rubygems_version: 2.
|
151
|
+
rubygems_version: 2.1.5
|
152
152
|
signing_key:
|
153
153
|
specification_version: 3
|
154
154
|
summary: An ActiveRecord-like model that uses a hash or file as a datasource
|