public
Description: Allows the caching of lookup data in your Rails models
Clone URL: git://github.com/vigetlabs/constant_cache.git
Search Repo:
Improved documentation
Add String#constant_name directly
reagent (author)
Mon Apr 14 22:41:42 -0700 2008
commit  da8ecd91d84250328d72035562525d61e1c1ea5c
tree    d3fa4929fd1d1aa825084555bd043e71e5483e83
parent  763901ee6af5f0c5d64d7ec35e41c6a0825ab9ba
...
1
2
 
...
1
2
3
0
@@ -1,3 +1,4 @@
0
 pkg
0
 coverage
0
+doc
...
 
 
 
 
 
 
1
2
3
...
1
2
3
4
5
6
7
8
9
0
@@ -1,3 +1,9 @@
0
+== 0.0.2 2009-04-??
0
+
0
+* Enhancements
0
+ * Better documentation
0
+ * Modify String class directly instead of using a mix-in
0
+
0
 == 0.0.1 2008-04-08
0
 
0
 * 1 major enhancement:
0
...
1
2
 
3
4
5
6
7
...
21
22
23
24
 
25
26
27
28
29
30
31
 
32
33
34
35
36
37
38
 
39
40
41
...
72
73
74
75
 
 
 
 
 
 
...
 
 
1
2
3
4
5
6
...
20
21
22
 
23
24
25
26
27
28
 
 
29
30
31
32
33
34
 
 
35
36
37
38
...
69
70
71
 
72
73
74
75
76
77
0
@@ -1,5 +1,4 @@
0
-ConstantCache
0
-===============
0
+= Constant Cache
0
 
0
 When your database has tables that store lookup data, there is a tendency
0
 to provide those values as constants in the model. If you have an
0
0
0
@@ -21,21 +20,19 @@
0
 with the data that's in the table (not necessarily a bad thing), but this
0
 solution forces you to write code like this:
0
 
0
-Account.new(:username => 'preagan', :status => AccountStatus.find(AccountStatus::PENDING))
0
+ Account.new(:username => 'preagan', :status => AccountStatus.find(AccountStatus::PENDING))
0
 
0
 This requires multiple calls to find and obfuscates the code a bit. Since classes
0
 in Ruby are executable code, we can cache the objects from the database at runtime
0
 and use them in your application.
0
 
0
-Installation
0
-============
0
+== Installation
0
 
0
 This code is packaged as a gem, so simply use the `gem` command to install:
0
 
0
   gem install constant_cache
0
 
0
-Example
0
-=======
0
+== Example
0
 
0
 "Out of the box," the constant_cache gem assumes that you want to use the 'name' column to generate
0
 constants from a column called 'name' in your database table. Assuming this schema:
0
@@ -72,5 +69,10 @@
0
     caches_constants :limit => 16
0
   end
0
 
0
-Copyright (c) 2007 Patrick Reagan of Viget Labs (patrick.reagan@viget.com), released under the MIT license
0
+== Acknowlegements
0
+
0
+Thanks to Dave Thomas for inspiring me to write this during his Metaprogramming talk at a Rails Edge
0
+conference in early 2007.
0
+
0
+Copyright (c) 2007 Patrick Reagan of Viget Labs (mailto:patrick.reagan@viget.com), released under the MIT license
...
26
27
28
29
30
 
31
32
33
...
26
27
28
 
 
29
30
31
32
0
@@ -26,8 +26,7 @@
0
   s.add_dependency('activesupport', '>= 2.0.2')
0
   
0
   s.require_path = 'lib'
0
- s.autorequire = GEM
0
- s.files = %w(MIT-LICENSE README Rakefile HISTORY) + Dir.glob("{lib,spec}/**/*")
0
+ s.files = %w(MIT-LICENSE README Rakefile HISTORY) + Dir.glob("{lib,spec}/**/*")
0
 end
0
 
0
 Rake::GemPackageTask.new(spec) do |pkg|
...
1
 
2
3
4
5
6
...
 
1
2
3
 
4
5
0
@@ -1,7 +1,6 @@
0
-require 'constant_cache/format'
0
+require 'constant_cache/core_ext'
0
 require 'constant_cache/cache_methods'
0
 
0
-String.send(:include, ConstantCache::Format)
0
 ActiveRecord::Base.send(:extend, ConstantCache::CacheMethods::ClassMethods)
0
 ActiveRecord::Base.send(:include, ConstantCache::CacheMethods::InstanceMethods)
...
1
 
 
2
 
 
 
3
4
 
 
5
6
 
7
8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
10
11
12
 
13
14
15
16
17
18
...
18
19
20
21
 
22
23
24
25
 
26
 
 
 
27
28
29
30
 
 
 
 
31
32
33
...
1
2
3
4
5
6
7
8
 
9
10
11
 
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
 
45
46
47
48
49
50
51
...
51
52
53
 
54
55
56
57
58
59
60
61
62
63
64
65
66
 
67
68
69
70
71
72
73
0
@@ -1,15 +1,48 @@
0
 module ConstantCache
0
+
0
+ CHARACTER_LIMIT = 64
0
   
0
+ #
0
+ # Generated constant conflicts with an existing constant
0
+ #
0
   class DuplicateConstantError < StandardError; end
0
- class InvalidLimitError < StandardError; end
0
+ class InvalidLimitError < StandardError #:nodoc:
0
+ end
0
   
0
- module CacheMethods
0
+ module CacheMethods #:nodoc:
0
 
0
     module ClassMethods
0
+
0
+ #
0
+ # The caches_constants method is the core of the functionality behind this mix-in. It provides
0
+ # a simple interface to cache the data in the corresponding table as constants on the model:
0
+ #
0
+ # class Status
0
+ # caches_constants
0
+ # end
0
+ #
0
+ # It makes certain assumptions about your schema: the constant created is based off of a <tt>name</tt>
0
+ # column in the database and long names are truncated to ConstantCache::CHARACTER_LIMIT characters before
0
+ # being set as constants. If there is a 'Pending' status in the database, you will now have a
0
+ # Status::PENDING constant that points to an instance of ActiveRecord.
0
+ #
0
+ # Beyond the basics, some configuration is allowed. You can change both the column that is used to generate
0
+ # the constant and the truncation length:
0
+ #
0
+ # class State
0
+ # caches_constants :key => :abbreviation, :limit => 2
0
+ # end
0
+ #
0
+ # This will use the <tt>abbreviation</tt> column to generate constants and will truncate constant names to 2
0
+ # characters at the maximum.
0
+ #
0
+ # Note: In the event that a generated constant conflicts with an existing constant, a
0
+ # ConstantCache::DuplicateConstantError is raised.
0
+ #
0
       def caches_constants(additional_options = {})
0
         cattr_accessor :cache_options
0
 
0
- self.cache_options = {:key => :name, :limit => 64}.merge(additional_options)
0
+ self.cache_options = {:key => :name, :limit => ConstantCache::CHARACTER_LIMIT}.merge(additional_options)
0
         
0
         raise ConstantCache::InvalidLimitError, "Limit of #{self.cache_options[:limit]} is invalid" if self.cache_options[:limit] < 1
0
         find(:all).each {|model| model.set_instance_as_constant }
0
0
0
0
@@ -18,16 +51,23 @@
0
 
0
     module InstanceMethods
0
 
0
- def constant_name
0
+ def constant_name #:nodoc:
0
         constant_name = self.send(self.class.cache_options[:key].to_sym).constant_name
0
         constant_name = constant_name[0, self.class.cache_options[:limit]] unless constant_name.blank?
0
         constant_name
0
       end
0
+ private :constant_name
0
 
0
+ #
0
+ # Create a constant on the class that pointing to an instance
0
+ #
0
       def set_instance_as_constant
0
         const = constant_name
0
         if !const.blank?
0
- raise ConstantCache::DuplicateConstantError, "Constant #{self.class.to_s}::#{const} has already been defined" if self.class.const_defined?(const)
0
+ if self.class.const_defined?(const)
0
+ message = "Constant #{self.class.to_s}::#{const} has already been defined"
0
+ raise ConstantCache::DuplicateConstantError, message
0
+ end
0
           self.class.const_set(const, self) if !const.blank?
0
         end
0
       end
...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
0
@@ -1 +1,17 @@
0
+class String
0
+
0
+ #
0
+ # A method to create a constant name from the existing string. This method condenses
0
+ # multiple non-word characters into a single underscore:
0
+ #
0
+ # 'abc'.constant_name => 'ABC'
0
+ # 'Restaurants & Bars'.constant_name => 'RESTAURANTS_BARS'
0
+ #
0
+ def constant_name
0
+ value = self.strip.gsub(/\s+/, '_').gsub(/[^\w_]/, '').gsub(/_{2,}/, '_').upcase
0
+ value = nil if value.blank?
0
+ value
0
+ end
0
+
0
+end
...
1
2
3
4
5
6
7
8
9
...
 
 
 
 
 
 
 
 
 
0
@@ -1,10 +1 @@
0
-module ConstantCache
0
- module Format
0
- def constant_name
0
- value = self.strip.gsub(/\s+/, '_').gsub(/[^\w_]/, '').gsub(/_{2,}/, '_').upcase
0
- value = nil if value.blank?
0
- value
0
- end
0
- end
0
-end
...
1
2
3
 
4
5
6
 
7
8
9
...
1
2
 
3
4
5
 
6
7
8
9
0
@@ -1,9 +1,9 @@
0
 module ConstantCache
0
   
0
- module VERSION
0
+ module VERSION #:nodoc:
0
     MAJOR = 0
0
     MINOR = 0
0
- TINY = 1
0
+ TINY = 2
0
     
0
     STRING = [MAJOR, MINOR, TINY].join('.')
0
   end
...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
0
@@ -1 +1,34 @@
0
+require File.dirname(__FILE__) + '/../../spec_helper'
0
+
0
+describe String do
0
+
0
+ it "should upcase its characters" do
0
+ 'test'.constant_name.should == 'TEST'
0
+ end
0
+
0
+ it "should replace whitespace with a single underscore" do
0
+ "test this \tformat\nplease.".constant_name.should == 'TEST_THIS_FORMAT_PLEASE'
0
+ end
0
+
0
+ it "should remove leading and trailing whitespace" do
0
+ ' test '.constant_name.should == 'TEST'
0
+ end
0
+
0
+ it "should remove non-word characters" do
0
+ '!test?'.constant_name.should == 'TEST'
0
+ end
0
+
0
+ it "should not singularize plural name" do
0
+ 'tests'.constant_name.should == 'TESTS'
0
+ end
0
+
0
+ it "should return nil when all characters are removed" do
0
+ '?'.constant_name.should be_nil
0
+ end
0
+
0
+ it "should collapse multiple underscores" do
0
+ 'test__me'.constant_name.should == 'TEST_ME'
0
+ end
0
+
0
+end
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0
@@ -1,36 +1 @@
0
-require File.dirname(__FILE__) + '/../../spec_helper'
0
-
0
-describe String, "with constant_name method" do
0
-
0
- before { String.send(:include, ConstantCache::Format) }
0
-
0
- it "should upcase its characters" do
0
- 'test'.constant_name.should == 'TEST'
0
- end
0
-
0
- it "should replace whitespace with a single underscore" do
0
- "test this \tformat\nplease.".constant_name.should == 'TEST_THIS_FORMAT_PLEASE'
0
- end
0
-
0
- it "should remove leading and trailing whitespace" do
0
- ' test '.constant_name.should == 'TEST'
0
- end
0
-
0
- it "should remove non-word characters" do
0
- '!test?'.constant_name.should == 'TEST'
0
- end
0
-
0
- it "should not singularize plural name" do
0
- 'tests'.constant_name.should == 'TESTS'
0
- end
0
-
0
- it "should return nil when all characters are removed" do
0
- '?'.constant_name.should be_nil
0
- end
0
-
0
- it "should collapse multiple underscores" do
0
- 'test__me'.constant_name.should == 'TEST_ME'
0
- end
0
-
0
-end
...
5
6
7
8
9
10
11
12
...
27
28
29
30
31
32
33
...
5
6
7
 
 
8
9
10
...
25
26
27
 
28
29
30
0
@@ -5,8 +5,6 @@
0
 require 'activesupport'
0
 require 'activerecord'
0
 
0
-
0
-
0
 lib_dir = File.join(File.dirname(__FILE__), %w(.. lib constant_cache))
0
 
0
 Dir.glob("#{lib_dir}/*.rb").each {|file| require file }
0
@@ -27,7 +25,6 @@
0
 Spec::Runner.configuration.mock_with :mocha
0
 Spec::Runner.configuration.include ConstantCache::SpecHelper
0
 
0
-String.send(:include, ConstantCache::Format)
0
 ActiveRecord::Base.send(:include, ConstantCache::CacheMethods::InstanceMethods)
0
 ActiveRecord::Base.send(:extend, ConstantCache::CacheMethods::ClassMethods)
0
 
...
1
2
3
4
5
6
7
8
9
...
 
 
 
 
 
 
 
 
 
0
@@ -1,10 +1 @@
0
-lib_dir = File.dirname(__FILE__) + '/lib'
0
-# require File.dirname(__FILE__) + '/../../../config/boot'
0
-require 'rubygems'
0
-require 'test/unit'
0
-require 'mocha'
0
-require 'active_record'
0
-
0
-# Re-use plugin initialization
0
-require File.dirname(__FILE__) + '/lib/constant_cache'

Comments

    No one has commented yet.