ChristophPetschnig-constantrecord 0.0.2
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/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
|
+
|