ChristophPetschnig-constantrecord 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/Manifest +6 -0
- data/README.rdoc +87 -0
- data/Rakefile +23 -0
- data/constantrecord.gemspec +32 -0
- data/lib/constantrecord.rb +296 -0
- data/test/constantrecord_test.rb +84 -0
- metadata +64 -0
data/Manifest
ADDED
data/README.rdoc
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
= ConstantRecord
|
2
|
+
|
3
|
+
== Usage
|
4
|
+
|
5
|
+
class Currency < ConstantRecord::Base
|
6
|
+
data 'EUR', 'USD', 'CAD', 'GBP', 'CHF'
|
7
|
+
end
|
8
|
+
|
9
|
+
or
|
10
|
+
|
11
|
+
class MoreDetailedCurrency < ConstantRecord::Base
|
12
|
+
columns :short, :description
|
13
|
+
data ['EUR', 'Euro'],
|
14
|
+
['USD', 'United States dollar'],
|
15
|
+
['CAD', 'Canadian dollar'],
|
16
|
+
['GBP', 'British pound sterling'],
|
17
|
+
['CHF', 'Swiss franc']
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
Inside ActiveRecord, it works just like a "normal" ActiveRecord association:
|
22
|
+
|
23
|
+
class Invoice < ActiveRecord::Base
|
24
|
+
belongs_to :currency # via currency_id database column
|
25
|
+
|
26
|
+
def print_currency
|
27
|
+
# Currency#name is the default attribute
|
28
|
+
puts self.currency.name if self.currency
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
ConstantRecord is meant as a substitute for ActiveRecord for tables, that will
|
33
|
+
never change in the lifespan of a mongrel process. I.e. an application might
|
34
|
+
let the user select a state of the US. Most applications will never have a
|
35
|
+
feature where a user/admin can edit the list of US states. They are considered
|
36
|
+
constant.
|
37
|
+
|
38
|
+
In my current application, my main/parent class has about 35 child classes,
|
39
|
+
that use over 40 different constant classes. The use of ConstantRecord meant
|
40
|
+
an estimated 15 to 20 per cent speed gain for my application.
|
41
|
+
|
42
|
+
ConstantRecord classes don't need accociations:
|
43
|
+
|
44
|
+
class CanadianProvince < ConstantRecord::Base
|
45
|
+
data = 'Alberta', ...
|
46
|
+
has_many :people # is not necessary, will not work
|
47
|
+
end
|
48
|
+
|
49
|
+
If you want to fetch all people living in Alberta, use:
|
50
|
+
|
51
|
+
Person.find(:all, :conditions =>
|
52
|
+
{:province_id => CanadianProvince.find_by_name('Alberta').id}
|
53
|
+
|
54
|
+
If you ever think, ConstantRecord lacks key features of ActiveRecord, (submit
|
55
|
+
a patch or) create the table and derive you class from ActiveRecord instead.
|
56
|
+
This is a key design objective for ConstantRecord.
|
57
|
+
|
58
|
+
== Features
|
59
|
+
|
60
|
+
Currency.find(1) >> #<Currency:0x332cbf4 @id=1, @name="EUR">
|
61
|
+
|
62
|
+
Just as in a database table, #id starts with 1.
|
63
|
+
When +data+ is a simple Array, #name is the default attribute.
|
64
|
+
|
65
|
+
MoreDetailedCurrency.find(3) >> #<MoreDetailedCurrency:0x2c8d94c
|
66
|
+
@description="Canadian Dollar",
|
67
|
+
@id=3, @short="CAD">
|
68
|
+
|
69
|
+
Currency.find_by_name('CHF') >> #<Currency:0x2c86ef8 @id=3, @name="CHF">
|
70
|
+
|
71
|
+
MoreDetailedCurrency.find_by_short('CAD')
|
72
|
+
>> #<MoreDetailedCurrency:0x2c8d94c
|
73
|
+
@description="Canadian Dollar",
|
74
|
+
@id=3, @short="CAD">
|
75
|
+
|
76
|
+
Currency.count :all >> 5
|
77
|
+
|
78
|
+
|
79
|
+
As a matter of fact, a ConstantRecord will often be used as a select field in a
|
80
|
+
HTML form. Therefore it comes with a special feature, that is not ActiveRecord
|
81
|
+
compatible. In a Form you can use:
|
82
|
+
|
83
|
+
<%= f.select :currency_id, Currency.options_for_select %>
|
84
|
+
|
85
|
+
or
|
86
|
+
|
87
|
+
<%= f.select :currency_id, Currency.options_for_select(:include_null => true) %>
|
data/Rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# Rakefile for constantrecord
|
2
|
+
require 'rubygems'
|
3
|
+
require 'rake'
|
4
|
+
require 'echoe'
|
5
|
+
|
6
|
+
Echoe.new('constantrecord', '0.0.1') do |p|
|
7
|
+
p.description = "A tiny ActiveRecord substitute for small, never changing database tables."
|
8
|
+
p.url = "http://github.com/ChristophPetschnig/constantrecord"
|
9
|
+
p.author = "Christoph Petschnig"
|
10
|
+
p.email = "info@purevirtual.de"
|
11
|
+
p.ignore_pattern = ["tmp/*", "script/*", "rdoc/*", "pkg/*"]
|
12
|
+
p.development_dependencies = []
|
13
|
+
p.rdoc_pattern = /^(lib|bin|tasks|ext)|^README.rdoc|^CHANGELOG|^TODO|^MIT-LICENSE|^COPYING$/
|
14
|
+
end
|
15
|
+
|
16
|
+
Dir["#{File.dirname(__FILE__)}/tasks/*.rake"].sort.each { |ext| load ext }
|
17
|
+
|
18
|
+
|
19
|
+
task :default => :test
|
20
|
+
|
21
|
+
require 'rake/testtask'
|
22
|
+
|
23
|
+
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{constantrecord}
|
5
|
+
s.version = "0.0.2"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Christoph Petschnig"]
|
9
|
+
s.date = %q{2009-03-15}
|
10
|
+
s.description = %q{A tiny ActiveRecord substitute for small, never changing database tables.}
|
11
|
+
s.email = %q{}
|
12
|
+
s.extra_rdoc_files = ["lib/constantrecord.rb", "README.rdoc"]
|
13
|
+
s.files = ["lib/constantrecord.rb", "test/constantrecord_test.rb", "Rakefile",
|
14
|
+
"README.rdoc", "Manifest", "constantrecord.gemspec"]
|
15
|
+
s.has_rdoc = true
|
16
|
+
s.homepage = %q{http://github.com/ChristophPetschnig/constantrecord}
|
17
|
+
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Constantrecord", "--main", "README.rdoc"]
|
18
|
+
s.require_paths = ["lib"]
|
19
|
+
s.rubyforge_project = %q{constantrecord}
|
20
|
+
s.rubygems_version = %q{1.3.1}
|
21
|
+
s.summary = %q{A tiny ActiveRecord substitute for small, never changing database tables.}
|
22
|
+
|
23
|
+
if s.respond_to? :specification_version then
|
24
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
25
|
+
s.specification_version = 2
|
26
|
+
|
27
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
28
|
+
else
|
29
|
+
end
|
30
|
+
else
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,296 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2009 Christoph Petschnig
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
#++
|
23
|
+
|
24
|
+
module ConstantRecord #:nodoc:
|
25
|
+
# ConstantRecord::Base is a tiny ActiveRecord substitute for small, never
|
26
|
+
# changing database tables.
|
27
|
+
#
|
28
|
+
# == Usage:
|
29
|
+
#
|
30
|
+
# class Currency < ConstantRecord::Base
|
31
|
+
# data 'EUR', 'USD', 'CAD', 'GBP', 'CHF'
|
32
|
+
# end
|
33
|
+
#
|
34
|
+
# or
|
35
|
+
#
|
36
|
+
# class MoreDetailedCurrency < ConstantRecord::Base
|
37
|
+
# columns :short, :description
|
38
|
+
# data ['EUR', 'Euro'],
|
39
|
+
# ['USD', 'US Dollar'],
|
40
|
+
# ['CAD', 'Canadian Dollar'],
|
41
|
+
# ['GBP', 'British Pound sterling'],
|
42
|
+
# ['CHF', 'Swiss franc']
|
43
|
+
# end
|
44
|
+
#
|
45
|
+
# To show all records in a HTML select field, use:
|
46
|
+
#
|
47
|
+
# <%= f.select :currency_id, Currency.options_for_select %>
|
48
|
+
#
|
49
|
+
class Base
|
50
|
+
|
51
|
+
private
|
52
|
+
attr_writer :id, :name #:nodoc:
|
53
|
+
|
54
|
+
public
|
55
|
+
attr_reader :id, :name #:nodoc:
|
56
|
+
|
57
|
+
# Set the column names of the constant table.
|
58
|
+
# Default is one column called `name`
|
59
|
+
def self.columns(*args)
|
60
|
+
# remove the default column name
|
61
|
+
undef_method :name
|
62
|
+
|
63
|
+
i = 0
|
64
|
+
col_ar = args.collect do |column|
|
65
|
+
raise TypeError.new("You can only pass Symbol or String object to #{self}::columns.") unless column.kind_of?(Symbol) || column.kind_of?(String)
|
66
|
+
|
67
|
+
class_eval do
|
68
|
+
private
|
69
|
+
attr_writer column
|
70
|
+
public
|
71
|
+
attr_reader column
|
72
|
+
end
|
73
|
+
|
74
|
+
i += 1
|
75
|
+
[column.to_sym, i - 1]
|
76
|
+
end.flatten
|
77
|
+
|
78
|
+
@columns = Hash[*col_ar]
|
79
|
+
end
|
80
|
+
|
81
|
+
# Set the data. Arguments must be an Array.
|
82
|
+
def self.data(*args)
|
83
|
+
@data = args.collect{|arg| arg.kind_of?(Array) ? arg : [arg]}
|
84
|
+
end
|
85
|
+
|
86
|
+
# Constructor. Call with the <tt>id</tt> plus a list of the values.
|
87
|
+
#
|
88
|
+
# MyConstantRecord.new(1, 'value of column #1', 2, 3.333)
|
89
|
+
#
|
90
|
+
def initialize(id, *values)
|
91
|
+
@id = id
|
92
|
+
|
93
|
+
return if values.empty?
|
94
|
+
|
95
|
+
# set the instance variables
|
96
|
+
get_columns.each do |key, value|
|
97
|
+
instance_variable_set("@#{key}", values[value])
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
# Implement +find+. Warning: <tt>:conditions</tt> are only supported with <tt>:first</tt>!
|
102
|
+
def self.find(*args)
|
103
|
+
selector = args[0]
|
104
|
+
|
105
|
+
# find might get called on constant_record_id.nil? == true
|
106
|
+
return nil if selector.nil?
|
107
|
+
|
108
|
+
raise TypeError.new("#{self}.find failed!\nArguments: #{args.inspect}") unless selector.kind_of?(Symbol) || selector.kind_of?(Fixnum)
|
109
|
+
|
110
|
+
if selector == :first
|
111
|
+
conditions = args[1][:conditions]
|
112
|
+
|
113
|
+
raise TypeError.new("#{self}.find failed!\nArguments: #{args.inspect}") unless conditions.kind_of?(Hash) && conditions.size == 1
|
114
|
+
|
115
|
+
compare_col_nr = get_columns[conditions.keys[0]]
|
116
|
+
raise "Unknown column :#{conditions.keys[0]}" unless compare_col_nr
|
117
|
+
|
118
|
+
@data.each_with_index do |datum, i|
|
119
|
+
return self.new(i, *datum) if datum[compare_col_nr] == conditions.values[0]
|
120
|
+
end
|
121
|
+
|
122
|
+
return nil
|
123
|
+
end
|
124
|
+
|
125
|
+
# ignore conditions on :all
|
126
|
+
return find_all if selector == :all
|
127
|
+
|
128
|
+
# ignore conditions if id is given as the first argument
|
129
|
+
return find_by_id(selector) if selector.kind_of?(Fixnum)
|
130
|
+
|
131
|
+
raise "#{self}.find failed!\nArguments: #{args.inspect}"
|
132
|
+
end
|
133
|
+
|
134
|
+
# Implement +count+. Warning: <tt>:conditions</tt> are not supported!
|
135
|
+
def self.count(*args)
|
136
|
+
selector = args[0] || :all
|
137
|
+
raise TypeError.new("#{self}.count failed!\nArguments: #{args.inspect}") unless selector.kind_of?(Symbol)
|
138
|
+
|
139
|
+
# ignore conditions on :all
|
140
|
+
return @data.size if selector == :all
|
141
|
+
|
142
|
+
raise "#{self}.count failed!\nArguments: #{args.inspect}"
|
143
|
+
end
|
144
|
+
|
145
|
+
# A ConstantRecord will never be a new record
|
146
|
+
def new_record? #:nodoc:
|
147
|
+
false
|
148
|
+
end
|
149
|
+
|
150
|
+
# A ConstantRecord should never be empty
|
151
|
+
def empty? #:nodoc:
|
152
|
+
false
|
153
|
+
end
|
154
|
+
|
155
|
+
# Keep this to spot problems in integration with ActiveRecord
|
156
|
+
def method_missing(symbol, *args) #:nodoc:
|
157
|
+
p "ConstantRecord::Base#method_missing(#{symbol})"
|
158
|
+
super symbol, *args
|
159
|
+
end
|
160
|
+
|
161
|
+
# Keep this to spot problems in integration with ActiveRecord
|
162
|
+
def respond_to?(symbol) #:nodoc:
|
163
|
+
result = super(symbol)
|
164
|
+
p "ConstantRecord::Base#respond_to?(#{symbol}) => #{result}(#{self.class})" unless result
|
165
|
+
result
|
166
|
+
end
|
167
|
+
|
168
|
+
# Handle +find_by_xxx+ calls on the class
|
169
|
+
def self.method_missing(symbol, *args) #:nodoc:
|
170
|
+
if /^find_by_([_a-zA-Z]\w*)$/ =~ (symbol.to_s)
|
171
|
+
return find(:first, :conditions => {$1.to_sym => args[0]})
|
172
|
+
end
|
173
|
+
p "ConstantRecord::Base::method_missing(#{symbol})"
|
174
|
+
super symbol, *args
|
175
|
+
end
|
176
|
+
|
177
|
+
# Keep this to spot problems in integration with ActiveRecord
|
178
|
+
def self.respond_to?(symbol) #:nodoc:
|
179
|
+
result = super symbol
|
180
|
+
p "ConstantRecord::Base::respond_to?(#{symbol}) => #{result}(#{self.class})" unless result
|
181
|
+
result
|
182
|
+
end
|
183
|
+
|
184
|
+
# Creates options for a select box in a form. The result is basically the same as
|
185
|
+
# the following code with ActiveRecord:
|
186
|
+
#
|
187
|
+
# MyActiveRecord.find(:all).collect{|obj| [obj.name, obj.id]}
|
188
|
+
#
|
189
|
+
# === Usage
|
190
|
+
#
|
191
|
+
# With the class:
|
192
|
+
#
|
193
|
+
# class Currency < ConstantRecord::Base
|
194
|
+
# columns :short, :description
|
195
|
+
# data ['EUR', 'Euro'],
|
196
|
+
# ['USD', 'US Dollar']
|
197
|
+
# end
|
198
|
+
#
|
199
|
+
# The following erb code:
|
200
|
+
#
|
201
|
+
# <%= f.select :currency_id, Currency.options_for_select %>
|
202
|
+
#
|
203
|
+
# Results to:
|
204
|
+
#
|
205
|
+
# <select id="invoice_currency_id" name="invoice[currency_id]">
|
206
|
+
# <option value="1">EUR</option>
|
207
|
+
# <option value="2">USD</option>
|
208
|
+
# </select>
|
209
|
+
#
|
210
|
+
# While:
|
211
|
+
#
|
212
|
+
# <%= f.select :currency_id, Currency.options_for_select(
|
213
|
+
# :display => Proc.new { |obj| "#{obj.short} (#{obj.description})" },
|
214
|
+
# :value => :short, :include_null => true,
|
215
|
+
# :null_text => 'Please choose one', :null_value => nil ) %>
|
216
|
+
#
|
217
|
+
# Results to:
|
218
|
+
#
|
219
|
+
# <select id="invoice_currency_id" name="invoice[currency_id]">
|
220
|
+
# <option value="">Please choose one</option>
|
221
|
+
# <option value="EUR">EUR (Euro)</option>
|
222
|
+
# <option value="USD">USD (US Dollar)</option>
|
223
|
+
# </select>
|
224
|
+
#
|
225
|
+
# === Options
|
226
|
+
#
|
227
|
+
# [:display]
|
228
|
+
# The attribute to call to display the text in the select box or a Proc object.
|
229
|
+
# [:value]
|
230
|
+
# The value to use for the option value. Default is the id of the record.
|
231
|
+
# [:include_null]
|
232
|
+
# Make an entry with the value 0 in the selectbox. Default is +false+.
|
233
|
+
# [:null_text]
|
234
|
+
# The text to show with on value 0. Default is '-'.
|
235
|
+
# [:null_value]
|
236
|
+
# The value of the null option. Default is 0.
|
237
|
+
def self.options_for_select(options = {})
|
238
|
+
display = options[:display] || get_columns.invert[0]
|
239
|
+
raise "#{self}.options_for_select: :display must be either Symbol or Proc." unless display.kind_of?(Symbol) ||display.kind_of?(Proc)
|
240
|
+
|
241
|
+
if display.kind_of?(Symbol)
|
242
|
+
display_col_nr = get_columns[display]
|
243
|
+
raise "Unknown column :#{display}" unless display_col_nr
|
244
|
+
end
|
245
|
+
|
246
|
+
value = options[:value] || :id
|
247
|
+
|
248
|
+
i = 0
|
249
|
+
result = @data.collect do |datum|
|
250
|
+
i += 1
|
251
|
+
obj = self.new(i, *datum)
|
252
|
+
option_show = display.kind_of?(Symbol) ? datum[display_col_nr] : display.call(obj)
|
253
|
+
option_value = value == :id ? i : obj.send(value)
|
254
|
+
|
255
|
+
[option_show, option_value]
|
256
|
+
end
|
257
|
+
|
258
|
+
if options[:include_null] == true
|
259
|
+
result.unshift [ options[:null_text] || '-', options.key?(:null_value) ? options[:null_value] : 0 ]
|
260
|
+
end
|
261
|
+
|
262
|
+
result
|
263
|
+
end
|
264
|
+
|
265
|
+
private
|
266
|
+
|
267
|
+
# Get the name of the columns or the default value
|
268
|
+
def self.get_columns
|
269
|
+
# if columns were not set, the default value is one column
|
270
|
+
# with the name of "name"
|
271
|
+
@columns || { :name => 0 }
|
272
|
+
end
|
273
|
+
|
274
|
+
def get_columns #:nodoc:
|
275
|
+
self.class.get_columns
|
276
|
+
end
|
277
|
+
|
278
|
+
# Implementation of +find+(:all)
|
279
|
+
def self.find_all #:nodoc:
|
280
|
+
i = 0
|
281
|
+
@data.collect do |datum|
|
282
|
+
i += 1
|
283
|
+
self.new(i, *datum)
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
# Implementation of +find+(:id)
|
288
|
+
def self.find_by_id(id) #:nodoc:
|
289
|
+
# check for valid range of selector
|
290
|
+
return nil if id <= 0 || id > @data.size
|
291
|
+
|
292
|
+
self.new(id, *@data[id - 1])
|
293
|
+
end
|
294
|
+
|
295
|
+
end
|
296
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'constantrecord'
|
2
|
+
require 'test/unit'
|
3
|
+
|
4
|
+
class SimpleClass < ConstantRecord::Base
|
5
|
+
data 'Lithuania', 'Latvia', 'Estonia'
|
6
|
+
end
|
7
|
+
|
8
|
+
class SimpleClass2 < ConstantRecord::Base
|
9
|
+
columns :album
|
10
|
+
data 'Sgt. Pepper', 'Magical Mystery Tour', 'Abbey Road'
|
11
|
+
end
|
12
|
+
|
13
|
+
class MultiColumnClass < ConstantRecord::Base
|
14
|
+
columns :short, :description
|
15
|
+
data ['EUR', 'Euro'],
|
16
|
+
['USD', 'US Dollar'],
|
17
|
+
['CAD', 'Canadian Dollar'],
|
18
|
+
['GBP', 'British Pound sterling'],
|
19
|
+
['CHF', 'Swiss franc']
|
20
|
+
end
|
21
|
+
|
22
|
+
class TestConstantRecord < Test::Unit::TestCase
|
23
|
+
def test_simple_finder
|
24
|
+
assert_equal 'Estonia', SimpleClass.find(3).name
|
25
|
+
assert_equal 3, SimpleClass.find(3).id
|
26
|
+
assert_nil SimpleClass.find(4)
|
27
|
+
assert_nil SimpleClass.find(0)
|
28
|
+
assert_nil SimpleClass.find(nil)
|
29
|
+
assert_equal 'Estonia', SimpleClass.find_by_name('Estonia').name
|
30
|
+
assert_equal 3, SimpleClass.find_by_name('Estonia').id
|
31
|
+
assert_raise (RuntimeError) { SimpleClass.find_by_foo('bar') }
|
32
|
+
assert_equal [ 'Lithuania', 'Latvia', 'Estonia' ], SimpleClass.find(:all).collect{|o| o.name}
|
33
|
+
assert_equal [ 1, 2, 3 ], SimpleClass.find(:all).collect{|o| o.id}
|
34
|
+
assert_equal 3, SimpleClass.count
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_simple_finder_with_custom_column_name
|
38
|
+
assert_equal 'Abbey Road', SimpleClass2.find(3).album
|
39
|
+
assert_equal 3, SimpleClass2.find(3).id
|
40
|
+
assert_nil SimpleClass2.find(4)
|
41
|
+
assert_nil SimpleClass2.find(0)
|
42
|
+
assert_nil SimpleClass2.find(nil)
|
43
|
+
assert_equal 'Sgt. Pepper', SimpleClass2.find_by_album('Sgt. Pepper').album
|
44
|
+
assert_equal 1, SimpleClass2.find_by_album('Sgt. Pepper').id
|
45
|
+
assert_raise (RuntimeError) { SimpleClass2.find_by_name('Sgt. Pepper') }
|
46
|
+
assert_equal [ 'Sgt. Pepper', 'Magical Mystery Tour', 'Abbey Road' ], SimpleClass2.find(:all).collect{|o| o.album}
|
47
|
+
assert_equal [ 1, 2, 3 ], SimpleClass2.find(:all).collect{|o| o.id}
|
48
|
+
assert_equal 3, SimpleClass2.count
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_multi_column_finder
|
52
|
+
all = MultiColumnClass.find(:all)
|
53
|
+
chf = all[4]
|
54
|
+
assert 5 == chf.id && chf.short && 'Swiss franc' == chf.description
|
55
|
+
|
56
|
+
assert_equal 'Canadian Dollar', MultiColumnClass.find_by_short('CAD').description
|
57
|
+
assert_equal 3, MultiColumnClass.find_by_short('CAD').id
|
58
|
+
|
59
|
+
assert_nil MultiColumnClass.find(6)
|
60
|
+
assert_nil MultiColumnClass.find(0)
|
61
|
+
assert_nil MultiColumnClass.find(nil)
|
62
|
+
assert_raise (RuntimeError) { MultiColumnClass.find_by_name('EUR') }
|
63
|
+
assert_equal [ 'EUR', 'USD', 'CAD', 'GBP', 'CHF' ], MultiColumnClass.find(:all).collect{|o| o.short}
|
64
|
+
assert_equal [ 1, 2, 3, 4, 5 ], MultiColumnClass.find(:all).collect{|o| o.id}
|
65
|
+
assert_equal 5, MultiColumnClass.count
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_options_for_select
|
69
|
+
assert_equal [['Lithuania', 1], ['Latvia', 2], ['Estonia', 3]], SimpleClass.options_for_select
|
70
|
+
assert_equal [['n/a', 0], ['Lithuania', 1], ['Latvia', 2], ['Estonia', 3]],
|
71
|
+
SimpleClass.options_for_select(:include_null => true, :null_text => 'n/a')
|
72
|
+
assert_equal [['-', nil], ['Lithuania', 1], ['Latvia', 2], ['Estonia', 3]],
|
73
|
+
SimpleClass.options_for_select(:include_null => true, :null_value => nil)
|
74
|
+
assert_equal [['Euro', 1], ['US Dollar', 2], ['Canadian Dollar', 3],
|
75
|
+
['British Pound sterling', 4], ['Swiss franc', 5]],
|
76
|
+
MultiColumnClass.options_for_select(:display => :description)
|
77
|
+
assert_equal [['-', "nothn'"], ['Euro', 'EUR'], ['US Dollar', 'USD'],
|
78
|
+
['Canadian Dollar', 'CAD'], ['British Pound sterling', 'GBP'], ['Swiss franc', 'CHF']],
|
79
|
+
MultiColumnClass.options_for_select(:display => :description, :value => :short,
|
80
|
+
:include_null => true, :null_value => "nothn'")
|
81
|
+
assert_equal [['*Sgt. Pepper*', 1], ['*Magical Mystery Tour*', 2], ['*Abbey Road*', 3]],
|
82
|
+
SimpleClass2.options_for_select(:display => Proc.new{|obj| "*#{obj.album}*"})
|
83
|
+
end
|
84
|
+
end
|
metadata
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ChristophPetschnig-constantrecord
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Christoph Petschnig
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-03-15 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: A tiny ActiveRecord substitute for small, never changing database tables.
|
17
|
+
email: ""
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- lib/constantrecord.rb
|
24
|
+
- README.rdoc
|
25
|
+
files:
|
26
|
+
- lib/constantrecord.rb
|
27
|
+
- test/constantrecord_test.rb
|
28
|
+
- Rakefile
|
29
|
+
- README.rdoc
|
30
|
+
- Manifest
|
31
|
+
- constantrecord.gemspec
|
32
|
+
has_rdoc: true
|
33
|
+
homepage: http://github.com/ChristophPetschnig/constantrecord
|
34
|
+
post_install_message:
|
35
|
+
rdoc_options:
|
36
|
+
- --line-numbers
|
37
|
+
- --inline-source
|
38
|
+
- --title
|
39
|
+
- Constantrecord
|
40
|
+
- --main
|
41
|
+
- README.rdoc
|
42
|
+
require_paths:
|
43
|
+
- lib
|
44
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: "0"
|
49
|
+
version:
|
50
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: "1.2"
|
55
|
+
version:
|
56
|
+
requirements: []
|
57
|
+
|
58
|
+
rubyforge_project: constantrecord
|
59
|
+
rubygems_version: 1.2.0
|
60
|
+
signing_key:
|
61
|
+
specification_version: 2
|
62
|
+
summary: A tiny ActiveRecord substitute for small, never changing database tables.
|
63
|
+
test_files: []
|
64
|
+
|