remi-aux_codes 1.0.1
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.
- data/README.markdown +98 -0
- data/VERSION.yml +4 -0
- data/lib/aux_codes/migration.rb +24 -0
- data/lib/aux_codes.rb +178 -0
- data/spec/aux_code_spec.rb +205 -0
- data/spec/spec_helper.rb +21 -0
- metadata +60 -0
data/README.markdown
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
aux codes
|
|
2
|
+
=========
|
|
3
|
+
|
|
4
|
+
Way back when, when I was learning database development, a mentor of mine showed me
|
|
5
|
+
a technique that he liked to use to consolidate similar enumeration-esque database tables.
|
|
6
|
+
|
|
7
|
+
Often, applications have enumeration-esque tables that merely store simply key / value pairs,
|
|
8
|
+
typically a unique ID and a string. Take for instance, a `genders` table:
|
|
9
|
+
|
|
10
|
+
[ genders ]
|
|
11
|
+
[id] [name]
|
|
12
|
+
1 Male
|
|
13
|
+
2 Female
|
|
14
|
+
|
|
15
|
+
That's a bit of a waste of a table, *especially* if your application has *TONS* of tables
|
|
16
|
+
just like this. There's where aux codes (or auxilary codes) come in!
|
|
17
|
+
|
|
18
|
+
[ aux_codes ]
|
|
19
|
+
[id] [category_id] [name]
|
|
20
|
+
1 0 Genders <--- this defines a 'table' (because category_id = 0)
|
|
21
|
+
2 1 Male <--- these are under category_id 1 (Genders)
|
|
22
|
+
3 1 Female
|
|
23
|
+
4 0 Colors <--- defines a color 'table'
|
|
24
|
+
5 4 Red <--- category_id 4 = 'Colors', so this is a color
|
|
25
|
+
6 4 Blue
|
|
26
|
+
|
|
27
|
+
Simple, eh?
|
|
28
|
+
|
|
29
|
+
Now, this is great, but this might get in the way of our business logic or it might
|
|
30
|
+
dirty up our code. We don't want to always be using the AuxCode object with complex
|
|
31
|
+
queries ... we probable want a Gender object that behaves just like it would with a
|
|
32
|
+
full-blown genders table.
|
|
33
|
+
|
|
34
|
+
Gender = AuxCode.category('Gender').aux_code_class
|
|
35
|
+
|
|
36
|
+
# the Gender class is a full-blown ActiveRecord class
|
|
37
|
+
# that should behave as if there's actually a `genders` table!
|
|
38
|
+
|
|
39
|
+
Gender.find_by_name 'Male'
|
|
40
|
+
|
|
41
|
+
Gender.find_or_create_by_name 'Female'
|
|
42
|
+
|
|
43
|
+
Gender.create :name => 'Female'
|
|
44
|
+
|
|
45
|
+
male = Gender.new :name => 'Male'
|
|
46
|
+
male.save
|
|
47
|
+
|
|
48
|
+
Gender.find :conditions => ['name = ?', 'Male']
|
|
49
|
+
|
|
50
|
+
Gender.count
|
|
51
|
+
|
|
52
|
+
Gender.codes
|
|
53
|
+
Gender.code_names
|
|
54
|
+
Gender.aux_code
|
|
55
|
+
Gender.aux_codes
|
|
56
|
+
|
|
57
|
+
If you want to create all of these classes at once, as constants:
|
|
58
|
+
|
|
59
|
+
AuxCode.create_classes!
|
|
60
|
+
|
|
61
|
+
You can also access codes with a Hash-like syntax
|
|
62
|
+
|
|
63
|
+
AuxCode['Genders']['Male']
|
|
64
|
+
AuxCode[:Genders][:Female]
|
|
65
|
+
|
|
66
|
+
Gender[:Male]
|
|
67
|
+
|
|
68
|
+
Or with an Indifferent Hash-like syntax
|
|
69
|
+
|
|
70
|
+
AuxCode.genders['Male']
|
|
71
|
+
AuxCode.genders[:Male]
|
|
72
|
+
AuxCode.genders.male
|
|
73
|
+
|
|
74
|
+
Gender.male
|
|
75
|
+
|
|
76
|
+
# these all return the same result
|
|
77
|
+
Breed.find_by_name 'Golden Retriever'
|
|
78
|
+
Breed['Golden Retriever']
|
|
79
|
+
Breed[:golden_retriever]
|
|
80
|
+
Breed.golden_retriever
|
|
81
|
+
AuxCodes.breeds.golden_retriever
|
|
82
|
+
|
|
83
|
+
TODO
|
|
84
|
+
----
|
|
85
|
+
|
|
86
|
+
* custom fields, eg:
|
|
87
|
+
* `Breed#acronym`
|
|
88
|
+
* `Breed#description`
|
|
89
|
+
* `Breed#kennel_association_id` ...
|
|
90
|
+
* these need an easy way to be defined! `alias_attribute`?
|
|
91
|
+
* this needs to work in development mode, when the models are constantly being reloaded!
|
|
92
|
+
* you shouldn't have to know the name of the special field to use it ... something like `attr_string :name` could just grab the (first) string column!
|
|
93
|
+
* create (or update) method(s) for helping with the original AuxCode migration and for creating the special additional fields
|
|
94
|
+
|
|
95
|
+
NOTES
|
|
96
|
+
-----
|
|
97
|
+
|
|
98
|
+
this implementation is for ActiveRecord only! i hope to eventually make a similar DataMapper implementation
|
data/VERSION.yml
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#
|
|
2
|
+
# ActiveRecord migration for creating the aux_codes table
|
|
3
|
+
#
|
|
4
|
+
class CreateAuxCodes < ActiveRecord::Migration
|
|
5
|
+
|
|
6
|
+
def self.up
|
|
7
|
+
create_table :aux_codes, :comment => 'Auxilary Codes' do |t|
|
|
8
|
+
|
|
9
|
+
t.integer :aux_code_id, :comment => 'ID of parent aux code (Category)', :null => false
|
|
10
|
+
t.string :name, :comment => 'Name of Category code (or child code)', :null => false
|
|
11
|
+
|
|
12
|
+
%w( integer decimal string text boolean datetime ).each do |field_type|
|
|
13
|
+
t.column field_type.to_sym, "#{field_type}_field"
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
t.timestamps
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def self.down
|
|
21
|
+
drop_table :aux_codes
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
end
|
data/lib/aux_codes.rb
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
$:.unshift File.dirname(__FILE__)
|
|
2
|
+
|
|
3
|
+
%w( rubygems activerecord aux_codes/migration ).each {|lib| require lib }
|
|
4
|
+
|
|
5
|
+
class AuxCode < ActiveRecord::Base
|
|
6
|
+
|
|
7
|
+
validates_presence_of :name
|
|
8
|
+
validates_uniqueness_of :name, :scope => :aux_code_id
|
|
9
|
+
|
|
10
|
+
belongs_to :aux_code
|
|
11
|
+
alias code aux_code
|
|
12
|
+
alias category aux_code
|
|
13
|
+
|
|
14
|
+
has_many :aux_codes
|
|
15
|
+
alias codes aux_codes
|
|
16
|
+
|
|
17
|
+
before_create :set_default_values
|
|
18
|
+
|
|
19
|
+
def code_names
|
|
20
|
+
codes.map &:name
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def is_a_category?
|
|
24
|
+
aux_code_id == 0
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def class_name
|
|
28
|
+
name.gsub(/[^[:alpha:]]/,'_').titleize.gsub(' ','').singularize
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def [] attribute_or_code_name
|
|
32
|
+
if attributes.include?attribute_or_code_name
|
|
33
|
+
attributes[attribute_or_code_name]
|
|
34
|
+
else
|
|
35
|
+
found = codes.select {|c| c.name.to_s =~ /#{attribute_or_code_name}/ }
|
|
36
|
+
if found.empty? # try case insensitive (sans underscores)
|
|
37
|
+
found = codes.select {|c| c.name.downcase.gsub('_',' ').to_s =~
|
|
38
|
+
/#{attribute_or_code_name.to_s.downcase.gsub('_',' ')}/ }
|
|
39
|
+
end
|
|
40
|
+
found.first if found
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def method_missing_with_indifferent_hash_style_values name, *args, &block
|
|
45
|
+
method_missing_without_indifferent_hash_style_values name, *args, &block
|
|
46
|
+
rescue NoMethodError => ex
|
|
47
|
+
begin
|
|
48
|
+
self[name]
|
|
49
|
+
rescue
|
|
50
|
+
raise ex
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
alias_method_chain :method_missing, :indifferent_hash_style_values
|
|
54
|
+
|
|
55
|
+
def aux_code_class
|
|
56
|
+
klass = Class.new(AuxCode) do
|
|
57
|
+
class << self
|
|
58
|
+
attr_accessor :aux_code_id, :aux_code
|
|
59
|
+
|
|
60
|
+
def aux_code
|
|
61
|
+
# @aux_code ||= AuxCode.find aux_code_id
|
|
62
|
+
AuxCode.find aux_code_id
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def count_with_aux_code_scope options = {}
|
|
66
|
+
with_scope(:find => { :conditions => ['aux_code_id = ?', self.aux_code_id] }) do
|
|
67
|
+
count_without_aux_code_scope options
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
def method_missing_with_aux_code_scope name, *args, &block
|
|
71
|
+
if name.to_s[/^find/]
|
|
72
|
+
if name.to_s[/or_create_by_/]
|
|
73
|
+
name = "#{name}_and_aux_code_id".to_sym
|
|
74
|
+
args << self.aux_code_id
|
|
75
|
+
# method_missing_without_aux_code_scope name, *args
|
|
76
|
+
AuxCode.send name, *args, &block
|
|
77
|
+
else
|
|
78
|
+
with_scope(:find => { :conditions => ['aux_code_id = ?', self.aux_code_id] }) do
|
|
79
|
+
method_missing_without_aux_code_scope name, *args, &block
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
else
|
|
83
|
+
method_missing_without_aux_code_scope name, *args, &block
|
|
84
|
+
end
|
|
85
|
+
rescue NoMethodError => ex
|
|
86
|
+
begin
|
|
87
|
+
aux_code.send name, *args, &block # try on the AuxCode instance for this class ...
|
|
88
|
+
rescue
|
|
89
|
+
raise ex
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
def find_with_aux_code_scope first_or_all, options = {}
|
|
93
|
+
with_scope(:find => { :conditions => ['aux_code_id = ?', self.aux_code_id] }) do
|
|
94
|
+
find_without_aux_code_scope first_or_all, options
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
def create_with_aux_code_scope options = {}
|
|
98
|
+
create_without_aux_code_scope options.merge({ :aux_code_id => self.aux_code_id })
|
|
99
|
+
end
|
|
100
|
+
def create_with_aux_code_scope! options = {}
|
|
101
|
+
create_without_aux_code_scope! options.merge({ :aux_code_id => self.aux_code_id })
|
|
102
|
+
end
|
|
103
|
+
def new_with_aux_code_scope options = {}
|
|
104
|
+
new_without_aux_code_scope options.merge({ :aux_code_id => self.aux_code_id })
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
alias_method_chain :count, :aux_code_scope
|
|
108
|
+
alias_method_chain :method_missing, :aux_code_scope
|
|
109
|
+
alias_method_chain :find, :aux_code_scope
|
|
110
|
+
alias_method_chain :create, :aux_code_scope
|
|
111
|
+
alias_method_chain :create!, :aux_code_scope
|
|
112
|
+
alias_method_chain :new, :aux_code_scope
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
klass.aux_code_id = self.id # the class needs to know its own aux_code_id
|
|
117
|
+
klass
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
class << self
|
|
121
|
+
def categories
|
|
122
|
+
AuxCode.find_all_by_aux_code_id(0)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def category_names
|
|
126
|
+
AuxCode.categories.map &:name
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def category category_object_or_id_or_name
|
|
130
|
+
obj = category_object_or_id_or_name
|
|
131
|
+
return obj if obj.is_a?AuxCode
|
|
132
|
+
return AuxCode.find(obj) if obj.is_a?Fixnum
|
|
133
|
+
return AuxCode.find_by_name_and_aux_code_id(obj, 0) if obj.is_a?String
|
|
134
|
+
return AuxCode.find_by_name_and_aux_code_id(obj.to_s, 0) if obj.is_a?Symbol
|
|
135
|
+
raise "I don't know how to find an AuxCode of type #{ obj.class }"
|
|
136
|
+
end
|
|
137
|
+
alias [] category
|
|
138
|
+
|
|
139
|
+
def category_codes category_object_or_id_or_name
|
|
140
|
+
category( category_object_or_id_or_name ).codes
|
|
141
|
+
end
|
|
142
|
+
alias category_values category_codes
|
|
143
|
+
|
|
144
|
+
def category_code_names category_object_or_id_or_name
|
|
145
|
+
category( category_object_or_id_or_name ).code_names
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def create_classes!
|
|
149
|
+
AuxCode.categories.each do |category|
|
|
150
|
+
Kernel::const_set category.class_name, category.aux_code_class
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def method_missing_with_indifferent_hash_style_values name, *args, &block
|
|
155
|
+
unless self.respond_to?:aux_code_id # in which case, this is a *derived* class, not AuxCode
|
|
156
|
+
begin
|
|
157
|
+
method_missing_without_indifferent_hash_style_values name, *args, &block
|
|
158
|
+
rescue NoMethodError => ex
|
|
159
|
+
begin
|
|
160
|
+
self[name]
|
|
161
|
+
rescue
|
|
162
|
+
raise ex
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
else
|
|
166
|
+
method_missing_without_indifferent_hash_style_values name, *args, &block
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
alias_method_chain :method_missing, :indifferent_hash_style_values
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
protected
|
|
173
|
+
|
|
174
|
+
def set_default_values
|
|
175
|
+
self.aux_code_id = 0 unless aux_code_id
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
end
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
|
2
|
+
|
|
3
|
+
describe AuxCode do
|
|
4
|
+
|
|
5
|
+
it 'should require a name' do
|
|
6
|
+
AuxCode.create( :name => nil ).should_not be_valid
|
|
7
|
+
AuxCode.create( :name => ' ' ).should_not be_valid
|
|
8
|
+
AuxCode.create( :name => 'foo' ).should be_valid
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it 'should have many aux codes (if category)' do
|
|
12
|
+
code = AuxCode.create! :name => 'foo'
|
|
13
|
+
code.codes.should be_empty
|
|
14
|
+
w00t = code.codes.create :name => 'w00t'
|
|
15
|
+
code.codes.should include(w00t)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it 'should have code names (if category)' do
|
|
19
|
+
code = AuxCode.create! :name => 'foo'
|
|
20
|
+
code.codes.create :name => 'chunky'
|
|
21
|
+
code.codes.create :name => 'bacon'
|
|
22
|
+
|
|
23
|
+
code.codes.length.should == 2
|
|
24
|
+
code.code_names.length.should == 2
|
|
25
|
+
code.code_names.should include('chunky')
|
|
26
|
+
code.code_names.should include('bacon')
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "should know whether it's a category or a category value / code" do
|
|
30
|
+
code = AuxCode.create! :name => 'foo'
|
|
31
|
+
w00t = code.codes.create :name => 'w00t'
|
|
32
|
+
|
|
33
|
+
w00t.is_a_category?.should be_false
|
|
34
|
+
code.is_a_category?.should be_true
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it 'should belong to a category (if not a category)' do
|
|
38
|
+
code = AuxCode.create! :name => 'foo'
|
|
39
|
+
w00t = code.codes.create! :name => 'w00t'
|
|
40
|
+
w00t.aux_code.should == code
|
|
41
|
+
w00t.code.should == code
|
|
42
|
+
w00t.category.should == code
|
|
43
|
+
w00t.category.codes.should include(w00t)
|
|
44
|
+
|
|
45
|
+
w00t.codes.should be_empty
|
|
46
|
+
code.category.should be_nil
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it 'should require a name unique to category' do
|
|
50
|
+
first_category = AuxCode.create! :name => 'foo'
|
|
51
|
+
second_category = AuxCode.create! :name => 'bar'
|
|
52
|
+
|
|
53
|
+
first_category.aux_codes.create( :name => 'w00t' ).should be_valid
|
|
54
|
+
first_category.aux_codes.create( :name => 'w00t' ).should_not be_valid
|
|
55
|
+
second_category.aux_codes.create( :name => 'w00t' ).should be_valid
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it 'should be able to easily get all categories' do
|
|
59
|
+
AuxCode.categories.should be_empty
|
|
60
|
+
|
|
61
|
+
first_category = AuxCode.create! :name => 'foo'
|
|
62
|
+
second_category = AuxCode.create! :name => 'bar'
|
|
63
|
+
code_1 = first_category.codes.create :name => 'w00t'
|
|
64
|
+
code_2 = first_category.codes.create :name => 'w00t'
|
|
65
|
+
|
|
66
|
+
AuxCode.categories.should include(first_category)
|
|
67
|
+
AuxCode.categories.should include(second_category)
|
|
68
|
+
AuxCode.categories.should_not include(code_1)
|
|
69
|
+
AuxCode.categories.should_not include(code_2)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
it 'should be able to easily get all category names' do
|
|
73
|
+
AuxCode.category_names.should be_empty
|
|
74
|
+
|
|
75
|
+
first_category = AuxCode.create! :name => 'foo'
|
|
76
|
+
second_category = AuxCode.create! :name => 'bar'
|
|
77
|
+
code_1 = first_category.codes.create :name => 'w00t'
|
|
78
|
+
|
|
79
|
+
AuxCode.category_names.should include('foo')
|
|
80
|
+
AuxCode.category_names.should include('bar')
|
|
81
|
+
AuxCode.category_names.should_not include('w00t')
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
it 'should be able to fetch a category give the category, its name, or its id' do
|
|
85
|
+
cat = AuxCode.create! :name => 'foo'
|
|
86
|
+
AuxCode.category( cat ).should == cat
|
|
87
|
+
AuxCode.category( cat.id ).should == cat
|
|
88
|
+
AuxCode.category( cat.name ).should == cat
|
|
89
|
+
AuxCode.category( cat.name.to_sym ).should == cat
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
it 'should be able to easily get all values (codes) for a category' do
|
|
93
|
+
first_category = AuxCode.create! :name => 'foo'
|
|
94
|
+
code_1 = first_category.codes.create :name => 'w00t'
|
|
95
|
+
code_2 = first_category.codes.create :name => 'chunky'
|
|
96
|
+
code_3 = first_category.codes.create :name => 'bacon'
|
|
97
|
+
|
|
98
|
+
[ AuxCode.category_values( first_category ), AuxCode.category_values( 'foo' ) ].each do |codes|
|
|
99
|
+
codes.should include(code_1)
|
|
100
|
+
codes.should include(code_2)
|
|
101
|
+
codes.should include(code_3)
|
|
102
|
+
codes.should_not include(first_category)
|
|
103
|
+
end
|
|
104
|
+
AuxCode.category_values( first_category ).should == AuxCode.category_codes( first_category )
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
it 'should be able to easily get all value names (code names) for a category' do
|
|
108
|
+
first_category = AuxCode.create! :name => 'foo'
|
|
109
|
+
code_1 = first_category.codes.create :name => 'w00t'
|
|
110
|
+
code_2 = first_category.codes.create :name => 'chunky'
|
|
111
|
+
code_3 = first_category.codes.create :name => 'bacon'
|
|
112
|
+
|
|
113
|
+
[ AuxCode.category_code_names( first_category ), AuxCode.category_code_names( 'foo' ) ].each do |codes|
|
|
114
|
+
codes.should include('w00t')
|
|
115
|
+
codes.should include('chunky')
|
|
116
|
+
codes.should include('bacon')
|
|
117
|
+
codes.should_not include('foo')
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
it 'should be able to get a Class for each category' do
|
|
122
|
+
random_category = AuxCode.create! :name => 'random-category-name'
|
|
123
|
+
foo_category = AuxCode.create! :name => 'foo'
|
|
124
|
+
foo_class = foo_category.aux_code_class
|
|
125
|
+
foo_class.count.should == 0
|
|
126
|
+
|
|
127
|
+
x = foo_category.codes.create :name => 'chunky'
|
|
128
|
+
foo_class.count.should == 1
|
|
129
|
+
|
|
130
|
+
foo_class.create :name => 'bacon'
|
|
131
|
+
foo_class.count.should == 2
|
|
132
|
+
|
|
133
|
+
foo = foo_class.create! :name => 'foo'
|
|
134
|
+
foo_class.count.should == 3
|
|
135
|
+
|
|
136
|
+
bar = foo_class.new :name => 'bar'
|
|
137
|
+
bar.save
|
|
138
|
+
foo_class.count.should == 4
|
|
139
|
+
|
|
140
|
+
w00t = foo_class.new :name => 'w00t'
|
|
141
|
+
w00t.save!
|
|
142
|
+
foo_class.count.should == 5
|
|
143
|
+
|
|
144
|
+
foo_class.find( :first, :conditions => ['name = ?', 'foo'] ).should == foo
|
|
145
|
+
foo_class.find( :first, :conditions => ['name = ?', 'foo'] ).should_not == foo_category
|
|
146
|
+
|
|
147
|
+
foo_class.find_by_name( 'foo' ).should == foo
|
|
148
|
+
foo_class.find_by_name( 'foo' ).should_not == foo_category
|
|
149
|
+
|
|
150
|
+
foo_class.find_all_by_name( 'foo' ).should include(foo)
|
|
151
|
+
foo_class.find_all_by_name( 'foo' ).should_not include(foo_category)
|
|
152
|
+
|
|
153
|
+
foo_class.all.should include(foo)
|
|
154
|
+
foo_class.all.should_not include(foo_category)
|
|
155
|
+
|
|
156
|
+
foo_class.find_by_name( 'neat' ).should be_nil
|
|
157
|
+
foo_class.find_or_create_by_name( 'neat' ).should_not be_nil
|
|
158
|
+
foo_class.find_by_name( 'neat' ).should_not be_nil
|
|
159
|
+
foo_class.code_names.should include('neat')
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
it 'should create good class names from category names for #create_classes!' do
|
|
163
|
+
AuxCode.new( :name => 'foos' ).class_name.should == 'Foo'
|
|
164
|
+
AuxCode.new( :name => 'foo Bars' ).class_name.should == 'FooBar'
|
|
165
|
+
AuxCode.new( :name => 'foo Bar lar Tars' ).class_name.should == 'FooBarLarTar'
|
|
166
|
+
AuxCode.new( :name => 'foo_Bar lar-Tars' ).class_name.should == 'FooBarLarTar'
|
|
167
|
+
AuxCode.new( :name => 'foo_Bar0lar1Tar5s' ).class_name.should == 'FooBarLarTar'
|
|
168
|
+
AuxCode.new( :name => 'Dog' ).class_name.should == 'Dog'
|
|
169
|
+
AuxCode.new( :name => 'Dogs' ).class_name.should == 'Dog'
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
it 'should be able to get categories and their values using Hash syntax' do
|
|
173
|
+
foo_category = AuxCode.create! :name => 'foo'
|
|
174
|
+
bar_category = AuxCode.create! :name => 'bar'
|
|
175
|
+
chunky = foo_category.codes.create :name => 'chunky'
|
|
176
|
+
bacon = foo_category.codes.create :name => 'bacon'
|
|
177
|
+
|
|
178
|
+
AuxCode['foo'].should == foo_category
|
|
179
|
+
AuxCode[:foo].should == foo_category
|
|
180
|
+
|
|
181
|
+
AuxCode['foo'][:chunky].should == chunky
|
|
182
|
+
AuxCode[:foo]['chunky'].should == chunky
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
it 'should be able to get categories and their values using indifferent Hash syntax' do
|
|
186
|
+
foo_category = AuxCode.create! :name => 'foo'
|
|
187
|
+
bar_category = AuxCode.create! :name => 'bar'
|
|
188
|
+
chunky = foo_category.codes.create :name => 'chunky'
|
|
189
|
+
bacon = foo_category.codes.create :name => 'bacon'
|
|
190
|
+
|
|
191
|
+
AuxCode.foo.should == foo_category
|
|
192
|
+
AuxCode.foo.chunky.should == chunky
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
it 'should be able to handle names with spaces (with Hash syntax)' do
|
|
196
|
+
foo_category = AuxCode.create! :name => 'foo'
|
|
197
|
+
bar_category = AuxCode.create! :name => 'bar'
|
|
198
|
+
chunky = foo_category.codes.create :name => 'I am Chunky'
|
|
199
|
+
bacon = foo_category.codes.create :name => 'Yay for Bacon'
|
|
200
|
+
|
|
201
|
+
foo_category.i_am_chunky.should == chunky
|
|
202
|
+
foo_category[:yay_for_bacon].should == bacon
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
end
|
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/../lib/aux_codes'
|
|
2
|
+
require 'spec'
|
|
3
|
+
|
|
4
|
+
ActiveRecord::Base.establish_connection :adapter => 'sqlite3', :database => ':memory:'
|
|
5
|
+
CreateAuxCodes.verbose = false
|
|
6
|
+
CreateAuxCodes.migrate :up
|
|
7
|
+
|
|
8
|
+
# use transactions
|
|
9
|
+
AuxCode; # hit one of the AR classes
|
|
10
|
+
Spec::Runner.configure do |config|
|
|
11
|
+
config.before(:each) do
|
|
12
|
+
ActiveRecord::Base.connection.increment_open_transactions
|
|
13
|
+
ActiveRecord::Base.connection.begin_db_transaction
|
|
14
|
+
end
|
|
15
|
+
config.after(:each) do
|
|
16
|
+
if ActiveRecord::Base.connection.open_transactions != 0
|
|
17
|
+
ActiveRecord::Base.connection.rollback_db_transaction
|
|
18
|
+
ActiveRecord::Base.connection.decrement_open_transactions
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: remi-aux_codes
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 1.0.1
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- remi
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
|
|
12
|
+
date: 2009-01-27 00:00:00 -08:00
|
|
13
|
+
default_executable:
|
|
14
|
+
dependencies: []
|
|
15
|
+
|
|
16
|
+
description: ActiveRecord plugin for easily managing lots of enumeration-type data
|
|
17
|
+
email: remi@remitaylor.com
|
|
18
|
+
executables: []
|
|
19
|
+
|
|
20
|
+
extensions: []
|
|
21
|
+
|
|
22
|
+
extra_rdoc_files: []
|
|
23
|
+
|
|
24
|
+
files:
|
|
25
|
+
- VERSION.yml
|
|
26
|
+
- README.markdown
|
|
27
|
+
- lib/aux_codes
|
|
28
|
+
- lib/aux_codes/migration.rb
|
|
29
|
+
- lib/aux_codes.rb
|
|
30
|
+
- spec/aux_code_spec.rb
|
|
31
|
+
- spec/spec_helper.rb
|
|
32
|
+
has_rdoc: true
|
|
33
|
+
homepage: http://github.com/remi/aux_codes
|
|
34
|
+
post_install_message:
|
|
35
|
+
rdoc_options:
|
|
36
|
+
- --inline-source
|
|
37
|
+
- --charset=UTF-8
|
|
38
|
+
require_paths:
|
|
39
|
+
- lib
|
|
40
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
41
|
+
requirements:
|
|
42
|
+
- - ">="
|
|
43
|
+
- !ruby/object:Gem::Version
|
|
44
|
+
version: "0"
|
|
45
|
+
version:
|
|
46
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
47
|
+
requirements:
|
|
48
|
+
- - ">="
|
|
49
|
+
- !ruby/object:Gem::Version
|
|
50
|
+
version: "0"
|
|
51
|
+
version:
|
|
52
|
+
requirements: []
|
|
53
|
+
|
|
54
|
+
rubyforge_project:
|
|
55
|
+
rubygems_version: 1.2.0
|
|
56
|
+
signing_key:
|
|
57
|
+
specification_version: 2
|
|
58
|
+
summary: ActiveRecord plugin for easily managing lots of enumeration-type data
|
|
59
|
+
test_files: []
|
|
60
|
+
|