named_instances 0.1.0 → 1.0.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.
@@ -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