active_hash 0.7.5 → 0.7.6

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,3 +1,11 @@
1
+ 2009-12-19
2
+ - Added ActiveHash::Enum (John Pignata)
3
+
4
+ 2009-12-10
5
+ - Fixed a bug where belongs_to associations would raise an error instead of returning
6
+ nil when the parent object didn't exist.
7
+ - Added #[] and #[]= accessors for more ActiveRecord-esque-ness. (Pat Nakajima & Dave Yeu)
8
+
1
9
  2009-12-01
2
10
  - Add marked_for_destruction? to be compatible with nested attributes (Brandon Keene)
3
11
  - Added second parameter to respond_to? and cleaned up specs (Brian Takita)
data/README.md CHANGED
@@ -282,10 +282,48 @@ In Rails, in development mode, it reloads the entire class, which reloads the fi
282
282
 
283
283
  NOTE: By default, .full_path refers to the current working directory. In a rails app, this will be RAILS_ROOT.
284
284
 
285
- ## Authors
285
+ ## Enum
286
+
287
+ ActiveHash can expose its data in an Enumeration by setting constants for each record. This allows records to be accessed in code through a constant set in the ActiveHash class.
286
288
 
287
- Written by Jeff Dean, Mike Dalessio and Ben Woosley
289
+ The field to be used as the constant is set using _enum_accessor_ which takes the name of a field as an argument.
290
+
291
+ class Country < ActiveHash::Base
292
+ extend ActiveHash::Enum
293
+ self.data = [
294
+ {:id => 1, :name => "US", :capital => "Washington, DC"},
295
+ {:id => 2, :name => "Canada", :capital => "Ottawa"},
296
+ {:id => 3, :name => "Mexico", :capital => "Mexico City"}
297
+ ]
298
+ enum_accessor :name
299
+ end
300
+
301
+ Records can be accessed by looking up the field constant:
302
+
303
+ >> Country::US.capital
304
+ => "Washington DC"
305
+ >> Country::MEXICO.id
306
+ => 3
307
+ >> Country::CANADA
308
+ => #<Country:0x10229fb28 @attributes={:name=>"Canada", :id=>2}
309
+
310
+ Constants are formed by first stripping all non-word characters and then upcasing the result. This means strings like "Blazing Saddles", "ReBar", "Mike & Ike" and "Ho! Ho! Ho!" become BLAZINGSADDLES, REBAR, MIKEIKE and HOHOHO.
311
+
312
+ The field specified as the _enum_accessor_ must contain unique data values.
313
+
314
+ ## Authors
288
315
 
289
- == Copyright
316
+ * Jeff Dean
317
+ * Mike Dalessio
318
+ * Ben Woosley
319
+ * John Pignata
320
+ * Pat Nakajima
321
+ * Brandon Keene
322
+ * Dave Yeu
323
+ * Brian Takita
324
+ * Corey Innis
325
+ * Peter Jaros
326
+
327
+ ## Copyright
290
328
 
291
329
  Copyright (c) 2009 Jeff Dean. See LICENSE for details.
data/Rakefile CHANGED
@@ -8,7 +8,7 @@ begin
8
8
  gem.summary = %Q{An ActiveRecord-like model that uses a hash or file as a datasource}
9
9
  gem.email = "jeff@zilkey.com"
10
10
  gem.homepage = "http://github.com/zilkey/active_hash"
11
- gem.authors = ["Jeff Dean", "Mike Dalessio", "Corey Innis", "Peter Jaros", "Brandon Keene", "Brian Takita", "Pat Nakajima"]
11
+ gem.authors = ["Jeff Dean", "Mike Dalessio", "Corey Innis", "Peter Jaros", "Brandon Keene", "Brian Takita", "Pat Nakajima", "John Pignata"]
12
12
  gem.add_dependency('activesupport', [">= 2.2.2"])
13
13
  end
14
14
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.7.5
1
+ 0.7.6
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{active_hash}
8
- s.version = "0.7.5"
8
+ s.version = "0.7.6"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
- s.authors = ["Jeff Dean", "Mike Dalessio", "Corey Innis", "Peter Jaros", "Brandon Keene", "Brian Takita", "Pat Nakajima"]
12
- s.date = %q{2009-12-01}
11
+ s.authors = ["Jeff Dean", "Mike Dalessio", "Corey Innis", "Peter Jaros", "Brandon Keene", "Brian Takita", "Pat Nakajima", "John Pignata"]
12
+ s.date = %q{2009-12-19}
13
13
  s.email = %q{jeff@zilkey.com}
14
14
  s.extra_rdoc_files = [
15
15
  "LICENSE",
@@ -30,11 +30,14 @@ Gem::Specification.new do |s|
30
30
  "lib/active_hash/base.rb",
31
31
  "lib/active_yaml/base.rb",
32
32
  "lib/associations/associations.rb",
33
+ "lib/enum/enum.rb",
33
34
  "spec/active_file/base_spec.rb",
34
35
  "spec/active_hash/base_spec.rb",
35
36
  "spec/active_yaml/base_spec.rb",
36
37
  "spec/associations/associations_spec.rb",
38
+ "spec/enum/enum_spec.rb",
37
39
  "spec/fixtures/array_rows.yml",
40
+ "spec/fixtures/boroughs.yml",
38
41
  "spec/fixtures/cities.yml",
39
42
  "spec/fixtures/countries.yml",
40
43
  "spec/fixtures/states.yml",
@@ -50,6 +53,7 @@ Gem::Specification.new do |s|
50
53
  "spec/active_hash/base_spec.rb",
51
54
  "spec/active_yaml/base_spec.rb",
52
55
  "spec/associations/associations_spec.rb",
56
+ "spec/enum/enum_spec.rb",
53
57
  "spec/spec_helper.rb"
54
58
  ]
55
59
 
@@ -1,5 +1,6 @@
1
- require 'activesupport'
1
+ require 'active_support'
2
2
  require 'active_hash/base'
3
3
  require 'active_file/base'
4
4
  require 'active_yaml/base'
5
5
  require 'associations/associations'
6
+ require 'enum/enum'
@@ -211,7 +211,13 @@ module ActiveHash
211
211
  def base_class
212
212
  ActiveHash::Base
213
213
  end
214
-
214
+
215
+ def reload
216
+ self.data = read_inheritable_attribute(:data)
217
+ end
218
+
219
+ private :reload
220
+
215
221
  end
216
222
 
217
223
  attr_reader :attributes
@@ -224,6 +230,14 @@ module ActiveHash
224
230
  end
225
231
  end
226
232
 
233
+ def [](key)
234
+ attributes[key]
235
+ end
236
+
237
+ def []=(key, val)
238
+ attributes[key] = val
239
+ end
240
+
227
241
  def id
228
242
  attributes[:id] ? attributes[:id] : nil
229
243
  end
@@ -27,7 +27,7 @@ module ActiveHash
27
27
  }.merge(options)
28
28
 
29
29
  define_method(association_id) do
30
- options[:class_name].constantize.find(send(options[:foreign_key]))
30
+ options[:class_name].constantize.find_by_id(send(options[:foreign_key]))
31
31
  end
32
32
 
33
33
  define_method("#{association_id}=") do |new_value|
@@ -0,0 +1,44 @@
1
+ module ActiveHash
2
+ module Enum
3
+
4
+ DuplicateConstant = Class.new(RuntimeError)
5
+
6
+ def enum_accessor(field_name)
7
+ @enum_accessor = field_name
8
+ reload
9
+ end
10
+
11
+ def insert(record)
12
+ super
13
+ set_constant(record) if enum_accessor?
14
+ end
15
+
16
+ private :insert
17
+
18
+ def set_constant(record)
19
+ if constant = constant_for(record.attributes[@enum_accessor])
20
+ self.const_set(constant, record)
21
+ end
22
+ end
23
+
24
+ private :set_constant
25
+
26
+ def enum_accessor?
27
+ !@enum_accessor.nil?
28
+ end
29
+
30
+ private :enum_accessor?
31
+
32
+ def constant_for(field_value)
33
+ if constant = field_value.dup
34
+ constant.gsub!(/[^A-Za-z]*/, "")
35
+ constant.upcase!
36
+ raise DuplicateConstant, "#{constant} is already defined on #{self.class.name}" if const_defined?(constant)
37
+ constant
38
+ end
39
+ end
40
+
41
+ private :constant_for
42
+ end
43
+
44
+ end
@@ -346,6 +346,19 @@ describe ActiveHash, "Base" do
346
346
  country = Country.new("foo" => :bar)
347
347
  country.attributes.should == {:foo => :bar}
348
348
  end
349
+
350
+ it "is works with #[]" do
351
+ Country.field :foo
352
+ country = Country.new(:foo => :bar)
353
+ country[:foo].should == :bar
354
+ end
355
+
356
+ it "is works with #[]=" do
357
+ Country.field :foo
358
+ country = Country.new
359
+ country[:foo] = :bar
360
+ country.foo.should == :bar
361
+ end
349
362
  end
350
363
 
351
364
  describe "reader methods" do
@@ -74,6 +74,12 @@ describe ActiveHash::Base, "associations" do
74
74
  city = City.create :country_id => country.id
75
75
  city.country.should == country
76
76
  end
77
+
78
+ it "returns nil when the record does not exist" do
79
+ City.belongs_to :country
80
+ city = City.create :country_id => 123
81
+ city.country.should be_nil
82
+ end
77
83
  end
78
84
 
79
85
  context "with an ActiveHash parent" do
@@ -83,6 +89,12 @@ describe ActiveHash::Base, "associations" do
83
89
  author = Author.create :city_id => city.id
84
90
  author.city.should == city
85
91
  end
92
+
93
+ it "returns nil when the record does not exist" do
94
+ Author.belongs_to :city
95
+ author = Author.create :city_id => 123
96
+ author.city.should be_nil
97
+ end
86
98
  end
87
99
 
88
100
  describe "#parent=" do
@@ -0,0 +1,55 @@
1
+ require 'spec/spec_helper'
2
+
3
+ describe ActiveHash::Base, "enum" do
4
+
5
+ before do
6
+ ActiveYaml::Base.set_root_path File.expand_path(File.dirname(__FILE__) + "/../fixtures")
7
+
8
+ class Borough < ActiveYaml::Base
9
+ extend ActiveHash::Enum
10
+ fields :name, :county, :population
11
+ end
12
+ end
13
+
14
+ after do
15
+ Object.send(:remove_const, :Borough)
16
+ end
17
+
18
+ describe "#enum_accessor" do
19
+ it "sets the field used for accessing records by constants" do
20
+ Borough.enum_accessor :name
21
+ Borough::BROOKLYN.should == Borough.find_by_name("Brooklyn")
22
+ end
23
+
24
+ it "ensures that values stored in the field specified are unique" do
25
+ lambda do
26
+ Class.new(ActiveHash::Base) do
27
+ extend ActiveHash::Enum
28
+ self.data = [
29
+ { :name => 'Woodford Reserve' },
30
+ { :name => 'Bulliet Bourbon' },
31
+ { :name => 'Woodford Reserve' }
32
+ ]
33
+ enum_accessor :name
34
+ end
35
+ end.should raise_error(ActiveHash::Enum::DuplicateConstant)
36
+ end
37
+
38
+ it "removes non-word characters from values before setting constants" do
39
+ Movie = Class.new(ActiveHash::Base) do
40
+ extend ActiveHash::Enum
41
+ self.data = [
42
+ {:name => 'Die Hard 2', :rating => '4.3'},
43
+ {:name => 'The Informant!', :rating => '4.3'},
44
+ {:name => 'In & Out', :rating => '4.3'}
45
+ ]
46
+ enum_accessor :name
47
+ end
48
+
49
+ Movie::DIEHARD.name.should == 'Die Hard 2'
50
+ Movie::THEINFORMANT.name.should == 'The Informant!'
51
+ Movie::INOUT.name.should == 'In & Out'
52
+ end
53
+ end
54
+
55
+ end
@@ -0,0 +1,20 @@
1
+ - id: 1
2
+ name: Manhattan
3
+ county: New York
4
+ population: 1634795
5
+ - id: 2
6
+ name: Brooklyn
7
+ county: Kings
8
+ population: 2556598
9
+ - id: 3
10
+ name: Queens
11
+ county: Queens
12
+ population: 2293007
13
+ - id: 4
14
+ name: Bronx
15
+ county: Bronx
16
+ population: 1391903
17
+ - id: 5
18
+ name: Staten Island
19
+ county: Richmond
20
+ population: 487407
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: 0.7.5
4
+ version: 0.7.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeff Dean
@@ -11,11 +11,12 @@ authors:
11
11
  - Brandon Keene
12
12
  - Brian Takita
13
13
  - Pat Nakajima
14
+ - John Pignata
14
15
  autorequire:
15
16
  bindir: bin
16
17
  cert_chain: []
17
18
 
18
- date: 2009-12-01 00:00:00 -05:00
19
+ date: 2009-12-19 00:00:00 -05:00
19
20
  default_executable:
20
21
  dependencies:
21
22
  - !ruby/object:Gem::Dependency
@@ -52,11 +53,14 @@ files:
52
53
  - lib/active_hash/base.rb
53
54
  - lib/active_yaml/base.rb
54
55
  - lib/associations/associations.rb
56
+ - lib/enum/enum.rb
55
57
  - spec/active_file/base_spec.rb
56
58
  - spec/active_hash/base_spec.rb
57
59
  - spec/active_yaml/base_spec.rb
58
60
  - spec/associations/associations_spec.rb
61
+ - spec/enum/enum_spec.rb
59
62
  - spec/fixtures/array_rows.yml
63
+ - spec/fixtures/boroughs.yml
60
64
  - spec/fixtures/cities.yml
61
65
  - spec/fixtures/countries.yml
62
66
  - spec/fixtures/states.yml
@@ -94,4 +98,5 @@ test_files:
94
98
  - spec/active_hash/base_spec.rb
95
99
  - spec/active_yaml/base_spec.rb
96
100
  - spec/associations/associations_spec.rb
101
+ - spec/enum/enum_spec.rb
97
102
  - spec/spec_helper.rb