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 CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- NmYzYzMzOTEwZTkwZDgxNGExMTAyMDAzOTk3NTAzOTU1NzI5ZjQ2Yg==
4
+ MTE0YzI0ZDYzNTQ0OTVmOTI1Zjk4MmZlZWZlNGNlNGVmZjEyMzAxMg==
5
5
  data.tar.gz: !binary |-
6
- NDVkZmJhOTQ4NGZiZWJjNGYzMmU1ZmJiMzZmZGVmZmJlNWZkMjNiYQ==
7
- !binary "U0hBNTEy":
6
+ YTQwOGViNjkwZWJlOTkzZWZiZDgxNGU0NDgwZDVkNzE4OWY2MTE5Nw==
7
+ SHA512:
8
8
  metadata.gz: !binary |-
9
- MDIzNDE2NGZhZmUzZGNlNzUxOTZlNGUzMzcyMTU3ODg5MTQ2NjhmYzg4ZGFj
10
- MDFkYzI5NzY3MTdkZmUzNThkOTFjNmU5ZDEwOGM2YWJhZTViZDkyYzk0YjRi
11
- NTAyYzA5YWUxZmU5ZDRlMjgwZDFiYWFlZDQ3NTVkYWU1MGI1NWM=
9
+ Y2U2MGUzZjdkZDg3ODYyM2Q1NDNmODgyNTY0YjM0N2U2ZTYyOGIzZmFlYWMz
10
+ MTBmNjBjMTVjZDFhMzU4M2Q5ODcxMmI4NzYxMGNlNWNiNTg2MjZhNGQ1MmZk
11
+ MmRhYTI0OWIzMzliNWFkN2E3ZjRmMDhmNmViNzg1ZTNlYjZjYjE=
12
12
  data.tar.gz: !binary |-
13
- MjE0MDlkMjg4MTU4M2Q4Njc5NzlkYTNjYmY4MWVmZWQ4ZDRhMDRiMTgwNjVl
14
- ZDQ3ZGEwOWI0MGMxMzBlYjdlMDVjNThkMmJlYWJjMTIzMjk4YTYwOTA5NjYw
15
- NGYyMDhiYmViYzM2ZDBkNGQxZTQ2Mzg5ZDk3OGI3ZTJiMTAyZTQ=
13
+ MTU4NzNmZjdiNzM1MzkyYjA4MTMxOTJjZjhkMzJhNTQ4MTMzYTQ5NGFkOWI1
14
+ YjRmYzRlZmRhMWRmYzQ1OWY0ZjY1ZWY4NGUyZDZmMjEwNGIwMzNjZjMzZTJl
15
+ NjhjMzZlNTFkOTA2MDU4YjQwZTMwN2U0ODhjNTY3NWM2ZWIwZmM=
data/CHANGELOG CHANGED
@@ -1,3 +1,7 @@
1
+ 2013-10-01 (v1.2.0)
2
+ - belongs_to is back!
3
+ - added support for primary key options for belongs_to (tomtaylor)
4
+
1
5
  2013-09-09 (v1.0.2)
2
6
  - `where(nil)` returns all results, like ActiveRecord (kugaevsky)
3
7
 
@@ -1,5 +1,5 @@
1
1
  module ActiveHash
2
2
  module Gem
3
- VERSION = "1.0.2"
3
+ VERSION = "1.2.0"
4
4
  end
5
5
  end
@@ -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.find_by_id(send(options[:foreign_key]))
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.id : nil
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] => id)
82
+ klass.where(options[:foreign_key] => primary_key_value)
70
83
  elsif klass.respond_to?(:scoped)
71
- klass.scoped(:conditions => {options[:foreign_key] => id})
84
+ klass.scoped(:conditions => {options[:foreign_key] => primary_key_value})
72
85
  else
73
- klass.send("find_all_by_#{options[:foreign_key]}", id)
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.find_by_id(send(options[:foreign_key]))
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.id : nil
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
- before do
61
- @included_book_1 = Book.create! :author_id => 1, :published => true
62
- @included_book_2 = Book.create! :author_id => 1, :published => false
63
- @excluded_book = Book.create! :author_id => 2, :published => true
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
- it "find the correct records" do
67
- Author.has_many :books
68
- author = Author.create :id => 1
69
- author.books.should == [@included_book_1, @included_book_2]
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
- it "return a scope so that we can apply further scopes" do
73
- Author.has_many :books
74
- author = Author.create :id => 1
75
- author.books.published.should == [@included_book_1]
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
- before do
81
- Author.field :city_id
82
- @included_author_1 = Author.create :city_id => 1
83
- @included_author_2 = Author.create :city_id => 1
84
- @excluded_author = Author.create :city_id => 2
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
- it "find the correct records" do
88
- City.has_many :authors
89
- city = City.create :id => 1
90
- city.authors.should == [@included_author_1, @included_author_2]
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
- it "uses the correct class name when passed" do
94
- City.has_many :writers, :class_name => "Author"
95
- city = City.create :id => 1
96
- city.writers.should == [@included_author_1, @included_author_2]
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.2
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.0.5
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