named_instances 0.1.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,8 @@
1
+ *.sw?
2
+ .DS_Store
3
+ coverage
4
+ rdoc
5
+ pkg
6
+ test/test.db
7
+ *.gem
8
+ .bundle
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source :rubygems
2
+ gemspec
@@ -0,0 +1,85 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ named_instances (0.1.0)
5
+
6
+ GEM
7
+ remote: http://rubygems.org/
8
+ specs:
9
+ abstract (1.0.0)
10
+ actionmailer (3.0.0)
11
+ actionpack (= 3.0.0)
12
+ mail (~> 2.2.5)
13
+ actionpack (3.0.0)
14
+ activemodel (= 3.0.0)
15
+ activesupport (= 3.0.0)
16
+ builder (~> 2.1.2)
17
+ erubis (~> 2.6.6)
18
+ i18n (~> 0.4.1)
19
+ rack (~> 1.2.1)
20
+ rack-mount (~> 0.6.12)
21
+ rack-test (~> 0.5.4)
22
+ tzinfo (~> 0.3.23)
23
+ activemodel (3.0.0)
24
+ activesupport (= 3.0.0)
25
+ builder (~> 2.1.2)
26
+ i18n (~> 0.4.1)
27
+ activerecord (3.0.0)
28
+ activemodel (= 3.0.0)
29
+ activesupport (= 3.0.0)
30
+ arel (~> 1.0.0)
31
+ tzinfo (~> 0.3.23)
32
+ activeresource (3.0.0)
33
+ activemodel (= 3.0.0)
34
+ activesupport (= 3.0.0)
35
+ activesupport (3.0.0)
36
+ arel (1.0.1)
37
+ activesupport (~> 3.0.0)
38
+ builder (2.1.2)
39
+ erubis (2.6.6)
40
+ abstract (>= 1.0.0)
41
+ i18n (0.4.1)
42
+ mail (2.2.7)
43
+ activesupport (>= 2.3.6)
44
+ mime-types
45
+ treetop (>= 1.4.5)
46
+ mime-types (1.16)
47
+ mocha (0.9.8)
48
+ rake
49
+ polyglot (0.3.1)
50
+ rack (1.2.1)
51
+ rack-mount (0.6.13)
52
+ rack (>= 1.0.0)
53
+ rack-test (0.5.6)
54
+ rack (>= 1.0)
55
+ rails (3.0.0)
56
+ actionmailer (= 3.0.0)
57
+ actionpack (= 3.0.0)
58
+ activerecord (= 3.0.0)
59
+ activeresource (= 3.0.0)
60
+ activesupport (= 3.0.0)
61
+ bundler (~> 1.0.0)
62
+ railties (= 3.0.0)
63
+ railties (3.0.0)
64
+ actionpack (= 3.0.0)
65
+ activesupport (= 3.0.0)
66
+ rake (>= 0.8.4)
67
+ thor (~> 0.14.0)
68
+ rake (0.8.7)
69
+ sqlite3-ruby (1.3.1)
70
+ thor (0.14.3)
71
+ thoughtbot-shoulda (2.11.1)
72
+ treetop (1.4.8)
73
+ polyglot (>= 0.3.1)
74
+ tzinfo (0.3.23)
75
+
76
+ PLATFORMS
77
+ ruby
78
+
79
+ DEPENDENCIES
80
+ mocha
81
+ named_instances!
82
+ rails (= 3.0.0)
83
+ rake
84
+ sqlite3-ruby
85
+ thoughtbot-shoulda
@@ -0,0 +1,20 @@
1
+ = Named Instances
2
+
3
+ Provides support for named instances in Rails.
4
+
5
+ Quick usage:
6
+
7
+ class Diagnosis < ActiveRecord::Base
8
+ has_named_instances :name
9
+ end
10
+
11
+ Diagnosis.create :name => "Diabetes Mellitus"
12
+
13
+ >> Diagnosis.get(:diabetes_mellitus)
14
+ => #<Diagnosis id: 52, name: "Diabetes Mellitus", created_at: "2009-10-07 15:41:50", updated_at: "2009-10-07 15:41:50">
15
+
16
+ Patches welcome, enjoy!
17
+
18
+ == Copyright
19
+
20
+ Copyright (c) 2009 - 2010 Jason Dew. See LICENSE for details.
@@ -0,0 +1,9 @@
1
+ require "bundler"
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ task :default => :test
5
+
6
+ desc "Run the tests"
7
+ task :test do
8
+ system "ruby -Itest test/named_instances_test.rb"
9
+ end
@@ -1,69 +1,2 @@
1
- require "rails"
2
-
3
- module NamedInstances
4
-
5
- class Railtie < Rails::Railtie
6
- initializer "named_instances.initialize" do |app|
7
- ActiveRecord::Base.send :extend, NamedInstances
8
- end
9
- end
10
-
11
- def has_named_instances(name_method = :value, options={})
12
- @named_instances_loaded = false
13
- @named_instances_name_method = name_method
14
- @find_options = options[:find_options]
15
-
16
- after_save { self.class.load_named_instances }
17
- end
18
-
19
- def named_instances_loaded?
20
- !! @named_instances_loaded
21
- end
22
-
23
- def name_method
24
- @named_instances_name_method
25
- end
26
-
27
- def get *names
28
- load_named_instances unless @named_instances_loaded
29
-
30
- name = names.map {|n| n.to_s }.join "_"
31
- key_name = "#{named_instances_prefix}_#{name}"
32
- result = Rails.cache.read(key_name)
33
-
34
- # gets are hard-coded and should always return something valid from the cache
35
- raise(ArgumentError, "NamedInstance does not exist: #{key_name}") unless result
36
-
37
- result
38
- end
39
-
40
- def named_instances_normalize name
41
- name.downcase.gsub(/[^a-z0-9]+/, '_').gsub(/_$/, '')
42
- end
43
-
44
- def named_instances_prefix
45
- "named_instances_#{self}"
46
- end
47
-
48
- def load_named_instances
49
- begin
50
- self.all(@find_options).each do |instance|
51
- if (@named_instances_name_method.is_a? String) or (@named_instances_name_method.is_a? Symbol)
52
- field_name = named_instances_normalize instance.send(@named_instances_name_method)
53
- key_name = "#{named_instances_prefix}_#{field_name}"
54
- else
55
- key_name = @named_instances_name_method.inject(named_instances_prefix) do |key_name, name_method|
56
- field_name = named_instances_normalize instance.send(name_method)
57
- key_name + "_#{field_name}"
58
- end
59
- end
60
-
61
- Rails.cache.write(key_name, instance)
62
- end
63
-
64
- @named_instances_loaded = true
65
- rescue Exception => e
66
- Rails.logger.error "Named Instances: exception ignored, class = #{self}, error = #{e.inspect}"
67
- end
68
- end
69
- end
1
+ require "named_instances/base"
2
+ require "named_instances/railtie" if defined?(Rails::Railtie)
@@ -0,0 +1,84 @@
1
+ module NamedInstances
2
+
3
+ def self.included base
4
+ base.extend ClassMethods
5
+ end
6
+
7
+ module ClassMethods
8
+
9
+ module InstanceMethods
10
+ def normalized_name
11
+ self.class.named_instances_normalize send(self.class.name_method)
12
+ end
13
+ end
14
+
15
+ def has_named_instances(name_method = :value)
16
+ @named_instances_loaded = false
17
+ @named_instances_name_method = name_method
18
+
19
+ after_save {|model| model.class.load_named_instances }
20
+ include InstanceMethods
21
+ end
22
+
23
+ def named_instances_loaded?
24
+ !! @named_instances_loaded
25
+ end
26
+
27
+ def name_method
28
+ @named_instances_name_method
29
+ end
30
+
31
+ def get name_or_names
32
+ load_named_instances unless @named_instances_loaded
33
+
34
+ if not name_or_names.is_a?(String) and name_or_names.respond_to? :map
35
+ name_or_names.map {|name| get_one name }
36
+ else
37
+ get_one name_or_names
38
+ end
39
+ end
40
+
41
+ def get_one name
42
+ return if name.blank?
43
+ key_name = "#{named_instances_prefix}_#{name}"
44
+
45
+ begin
46
+ Rails.cache.read key_name
47
+ rescue
48
+ load_named_instances
49
+ Rails.cache.read key_name
50
+ end
51
+ end
52
+
53
+ def named_instances_normalize name
54
+ name.downcase.gsub(/[',]/, '').gsub(/[^a-z0-9_]+/, '_').gsub(/_$/, '')
55
+ end
56
+
57
+ def named_instances_prefix
58
+ "named_instances_#{self}"
59
+ end
60
+
61
+ def load_named_instances
62
+ begin
63
+ all.each do |instance|
64
+ if (@named_instances_name_method.is_a? String) or (@named_instances_name_method.is_a? Symbol)
65
+ field_name = named_instances_normalize instance.send(@named_instances_name_method)
66
+ key_name = "#{named_instances_prefix}_#{field_name}"
67
+ else
68
+ key_name = @named_instances_name_method.inject(named_instances_prefix) do |key_name, name_method|
69
+ field_name = named_instances_normalize instance.send(name_method)
70
+ key_name + "_#{field_name}"
71
+ end
72
+ end
73
+
74
+ Rails.cache.write(key_name, instance)
75
+ end
76
+
77
+ @named_instances_loaded = true
78
+ rescue Exception => e
79
+ Rails.logger.info "Named Instances: exception ignored, class = #{self}, error = #{e.inspect}"
80
+ end
81
+ end
82
+
83
+ end
84
+ end
@@ -0,0 +1,9 @@
1
+ module NamedInstances
2
+
3
+ class Railtie < Rails::Railtie
4
+ initializer "named_instances.initialize" do |app|
5
+ ActiveRecord::Base.send :include, NamedInstances if defined?(ActiveRecord)
6
+ end
7
+ end
8
+
9
+ end
@@ -1,3 +1,3 @@
1
1
  module NamedInstances
2
- VERSION = "0.1.0"
2
+ VERSION = "1.0.0"
3
3
  end
@@ -0,0 +1,28 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "named_instances/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "named_instances"
7
+ s.version = NamedInstances::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Jason Dew"]
10
+ s.email = ["jason.dew@gmail.com"]
11
+ s.homepage = "http://github.com/jasondew/named_instances"
12
+ s.summary = "Model.get(:name)"
13
+ s.description = "Give cached access to ActiveRecord models for quicker and more readable data-based logic."
14
+
15
+ s.rubyforge_project = "named_instances"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+
22
+ s.add_dependency "activesupport"
23
+ s.add_dependency "i18n"
24
+
25
+ s.add_development_dependency "thoughtbot-shoulda"
26
+ s.add_development_dependency "mocha"
27
+ s.add_development_dependency "sqlite3-ruby"
28
+ end
@@ -0,0 +1,19 @@
1
+ require "rubygems"
2
+ require "active_record"
3
+
4
+ class Diagnosis < ActiveRecord::Base
5
+ include NamedInstances
6
+ has_named_instances :name
7
+ end
8
+
9
+ ActiveRecord::Base.establish_connection :adapter => 'sqlite3', :database => 'test/test.db'
10
+
11
+ ActiveRecord::Schema.define do
12
+ create_table :diagnoses, :force => true do |t|
13
+ t.string :name
14
+ t.timestamps
15
+ end
16
+
17
+ Diagnosis.create :name => "Hypertension"
18
+ Diagnosis.create :name => "Diabetes Mellitus"
19
+ end
@@ -0,0 +1,71 @@
1
+ require "test_helper"
2
+
3
+ class NamedInstancesTest < Test::Unit::TestCase
4
+ context "Named instances of an AR model" do
5
+
6
+ should "be able get instances" do
7
+ result = Diagnosis.get(:diabetes_mellitus)
8
+ assert_equal Diagnosis.find_by_name("Diabetes Mellitus"), result
9
+ end
10
+
11
+ should "reload after a save" do
12
+ Diagnosis.get(:diabetes_mellitus)
13
+ new_behavior = Diagnosis.create(:name=>"test1")
14
+
15
+ result = Diagnosis.get(:test1)
16
+ assert_equal new_behavior, result
17
+ end
18
+
19
+ should "not raise an error if it doesn't exist" do
20
+ assert_nothing_raised do
21
+ Diagnosis.get(:does_not_exist)
22
+ end
23
+ end
24
+
25
+ should "find deleted instances as well" do
26
+ Diagnosis.get(:diabetes_mellitus).destroy
27
+ Diagnosis.load_named_instances
28
+
29
+ assert Diagnosis.get(:diabetes_mellitus)
30
+ end
31
+
32
+ should "maintain the same class object id on get" do
33
+ result = Diagnosis.get(:diabetes_mellitus)
34
+ assert_equal Diagnosis.object_id, result.class.object_id
35
+ end
36
+
37
+ should "return the method used for naming" do
38
+ assert_equal(:name, Diagnosis.name_method)
39
+ end
40
+
41
+ should "accept an array of naming methods" do
42
+ Foo = Struct.new(:bar, :baz)
43
+ Foo.send(:include, NamedInstances)
44
+
45
+ foo1 = Foo.new("abc", "def")
46
+ foo2 = Foo.new("xyz", "zzz")
47
+
48
+ Foo.expects(:after_save)
49
+ Foo.expects(:all).returns([foo1, foo2])
50
+
51
+ Rails.cache.expects(:write).with("named_instances_NamedInstancesTest::Foo_abc_def", foo1)
52
+ Rails.cache.expects(:write).with("named_instances_NamedInstancesTest::Foo_xyz_zzz", foo2)
53
+
54
+ Foo.has_named_instances [:bar, :baz]
55
+ assert Foo.load_named_instances
56
+ end
57
+
58
+ should "not crash if the instances can't be loaded immediately" do
59
+ BadFoo = Struct.new(:bar, :baz)
60
+ BadFoo.send(:include, NamedInstances)
61
+
62
+ BadFoo.expects(:after_save)
63
+ BadFoo.expects(:all).raises(Exception)
64
+
65
+ Rails.expects(:logger).returns(mock(:info))
66
+ BadFoo.has_named_instances [:bar, :baz]
67
+ BadFoo.load_named_instances
68
+ end
69
+
70
+ end
71
+ end
@@ -0,0 +1,11 @@
1
+ require "rails"
2
+ require "active_support"
3
+ require "active_support/cache"
4
+
5
+ def Rails.cache
6
+ @cache ||= ActiveSupport::Cache::MemoryStore.new
7
+ end
8
+
9
+ def Rails.logger
10
+ @logger ||= Logger.new(STDOUT)
11
+ end
@@ -0,0 +1,15 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+ require 'mocha'
5
+ require 'rails_crutch'
6
+
7
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
8
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), 'fixtures'))
9
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
10
+
11
+ require 'named_instances'
12
+ require 'diagnosis'
13
+
14
+ class Test::Unit::TestCase
15
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: named_instances
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
5
- prerelease: false
4
+ hash: 23
5
+ prerelease:
6
6
  segments:
7
- - 0
8
7
  - 1
9
8
  - 0
10
- version: 0.1.0
9
+ - 0
10
+ version: 1.0.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Jason Dew
@@ -15,10 +15,79 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-10-14 00:00:00 -04:00
18
+ date: 2011-03-01 00:00:00 -05:00
19
19
  default_executable:
20
- dependencies: []
21
-
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: activesupport
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: i18n
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ hash: 3
44
+ segments:
45
+ - 0
46
+ version: "0"
47
+ type: :runtime
48
+ version_requirements: *id002
49
+ - !ruby/object:Gem::Dependency
50
+ name: thoughtbot-shoulda
51
+ prerelease: false
52
+ requirement: &id003 !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ hash: 3
58
+ segments:
59
+ - 0
60
+ version: "0"
61
+ type: :development
62
+ version_requirements: *id003
63
+ - !ruby/object:Gem::Dependency
64
+ name: mocha
65
+ prerelease: false
66
+ requirement: &id004 !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ hash: 3
72
+ segments:
73
+ - 0
74
+ version: "0"
75
+ type: :development
76
+ version_requirements: *id004
77
+ - !ruby/object:Gem::Dependency
78
+ name: sqlite3-ruby
79
+ prerelease: false
80
+ requirement: &id005 !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ hash: 3
86
+ segments:
87
+ - 0
88
+ version: "0"
89
+ type: :development
90
+ version_requirements: *id005
22
91
  description: Give cached access to ActiveRecord models for quicker and more readable data-based logic.
23
92
  email:
24
93
  - jason.dew@gmail.com
@@ -29,9 +98,21 @@ extensions: []
29
98
  extra_rdoc_files: []
30
99
 
31
100
  files:
32
- - lib/named_instances/version.rb
33
- - lib/named_instances.rb
101
+ - .gitignore
102
+ - Gemfile
103
+ - Gemfile.lock
34
104
  - LICENSE
105
+ - README.rdoc
106
+ - Rakefile
107
+ - lib/named_instances.rb
108
+ - lib/named_instances/base.rb
109
+ - lib/named_instances/railtie.rb
110
+ - lib/named_instances/version.rb
111
+ - named_instances.gemspec
112
+ - test/fixtures/diagnosis.rb
113
+ - test/named_instances_test.rb
114
+ - test/rails_crutch.rb
115
+ - test/test_helper.rb
35
116
  has_rdoc: true
36
117
  homepage: http://github.com/jasondew/named_instances
37
118
  licenses: []
@@ -55,18 +136,19 @@ required_rubygems_version: !ruby/object:Gem::Requirement
55
136
  requirements:
56
137
  - - ">="
57
138
  - !ruby/object:Gem::Version
58
- hash: 23
139
+ hash: 3
59
140
  segments:
60
- - 1
61
- - 3
62
- - 6
63
- version: 1.3.6
141
+ - 0
142
+ version: "0"
64
143
  requirements: []
65
144
 
66
145
  rubyforge_project: named_instances
67
- rubygems_version: 1.3.7
146
+ rubygems_version: 1.5.2
68
147
  signing_key:
69
148
  specification_version: 3
70
149
  summary: Model.get(:name)
71
- test_files: []
72
-
150
+ test_files:
151
+ - test/fixtures/diagnosis.rb
152
+ - test/named_instances_test.rb
153
+ - test/rails_crutch.rb
154
+ - test/test_helper.rb