Class: ConstantRecord::Base
- Inherits:
-
Object
- Object
- ConstantRecord::Base
- Defined in:
- lib/constantrecord.rb
Overview
ConstantRecord::Base is a tiny ActiveRecord substitute for small, never changing database tables.
Usage:
class Currency < ConstantRecord::Base
data 'EUR', 'USD', 'CAD', 'GBP', 'CHF'
end
or
class MoreDetailedCurrency < ConstantRecord::Base
columns :name, :description
data ['EUR', 'Euro'],
['USD', 'US Dollar'],
['CAD', 'Canadian Dollar'],
['GBP', 'British Pound sterling'],
['CHF', 'Swiss franc']
end
To show all records in a HTML select field, use:
<%= f.select :currency_id, Currency.options_for_select %>
Instance Attribute Summary collapse
-
#id ⇒ Object
readonly
:nodoc:.
-
#name ⇒ Object
readonly
:nodoc:.
Class Method Summary collapse
-
.[](name) ⇒ Object
shortcut to retrieve value for name - eases dynamic lookup.
-
.all(*args) ⇒ Object
shortcut to #find(:all).
-
.columns(*args) ⇒ Object
Set the column names of the constant table.
-
.count(*args) ⇒ Object
Implement
count. -
.data(*args) ⇒ Object
Set the data.
-
.find(*args) ⇒ Object
Implement
find. -
.first(*args) ⇒ Object
shortcut to #find(:first).
-
.ids ⇒ Object
Returns an array of all ids.
-
.last(*args) ⇒ Object
shortcut to #find(:last).
-
.logger ⇒ Object
Get the logger.
-
.logger=(value) ⇒ Object
Set the logger; ConstantRecord will try to use the Rails logger, if it’s there.
-
.match(*args) ⇒ Object
Rails 3.0: this method is checked in ActiveRecord::Base.compute_type.
-
.method_missing(symbol, *args) ⇒ Object
Handle
find_by_xxxcalls on the class. -
.names ⇒ Object
Returns an array of the first column of your data.
-
.options_for_select(options = {}) ⇒ Object
Creates options for a select box in a form.
-
.respond_to?(symbol) ⇒ Boolean
Keep this to spot problems in integration with ActiveRecord.
-
.table ⇒ Object
Show output in the form of ‘SELECT * FROM tablename;`.
Instance Method Summary collapse
- #[](attr) ⇒ Object
-
#destroyed? ⇒ Boolean
A ConstantRecord will never be destroyed.
-
#empty? ⇒ Boolean
A ConstantRecord should never be empty.
-
#initialize(id, *values) ⇒ Base
constructor
Constructor.
-
#method_missing(symbol, *args) ⇒ Object
Keep this to spot problems in integration with ActiveRecord.
-
#new_record? ⇒ Boolean
A ConstantRecord will never be a new record.
-
#respond_to?(symbol) ⇒ Boolean
Keep this to spot problems in integration with ActiveRecord.
Constructor Details
#initialize(id, *values) ⇒ Base
Constructor. Call with the id plus a list of the values.
MyConstantRecord.new(1, 'value of column #1', 2, 3.333)
63 64 65 66 67 68 69 70 71 72 |
# File 'lib/constantrecord.rb', line 63 def initialize(id, *values) @id = id return if values.empty? # set the instance variables get_columns.each do |key, value| instance_variable_set("@#{key}", values[value]) end end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(symbol, *args) ⇒ Object
Keep this to spot problems in integration with ActiveRecord
203 204 205 206 |
# File 'lib/constantrecord.rb', line 203 def method_missing(symbol, *args) #:nodoc: self.class.log(:debug, "#{self.class}#method_missing(:#{symbol})") super symbol, *args end |
Instance Attribute Details
#id ⇒ Object
:nodoc:
36 37 38 |
# File 'lib/constantrecord.rb', line 36 def id @id end |
#name ⇒ Object
:nodoc:
36 37 38 |
# File 'lib/constantrecord.rb', line 36 def name @name end |
Class Method Details
.[](name) ⇒ Object
shortcut to retrieve value for name - eases dynamic lookup
136 137 138 139 |
# File 'lib/constantrecord.rb', line 136 def self.[](name) ret = @data.detect{|datum| datum.first == name} ret ? ret.last : raise(ConstantNotFound, "No such #{self.name} constant: #{name}") end |
.all(*args) ⇒ Object
shortcut to #find(:all)
121 122 123 |
# File 'lib/constantrecord.rb', line 121 def self.all(*args) find_all end |
.columns(*args) ⇒ Object
Set the column names of the constant table. Default is one column called name
40 41 42 43 44 45 46 47 48 49 50 51 52 |
# File 'lib/constantrecord.rb', line 40 def self.columns(*args) # remove the default column name undef_method :name class << self undef_method :names end col_ar = build_column_methods(*args) @columns = Hash[*col_ar] build_array_over_column_methods end |
.count(*args) ⇒ Object
Implement count. Warning: :conditions are not supported!
142 143 144 145 146 147 148 149 150 |
# File 'lib/constantrecord.rb', line 142 def self.count(*args) selector = args[0] || :all raise TypeError.new("#{self}.count failed!\nArguments: #{args.inspect}") unless selector.kind_of?(Symbol) # ignore conditions on :all return @data.size if selector == :all raise ArgumentError.new("#{self}.count failed!\nArguments: #{args.inspect}") end |
.data(*args) ⇒ Object
Set the data. Arguments must be an Array.
55 56 57 |
# File 'lib/constantrecord.rb', line 55 def self.data(*args) @data = args.collect{|arg| arg.kind_of?(Array) ? arg : [arg]} end |
.find(*args) ⇒ Object
Implement find. Warning: :conditions are only supported with :first!
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
# File 'lib/constantrecord.rb', line 75 def self.find(*args) selector = args[0] # find might get called on constant_record_id.nil? == true return nil if selector.nil? raise TypeError.new("#{self}.find failed!\nArguments: #{args.inspect}") unless selector.kind_of?(Symbol) || selector.kind_of?(Fixnum) case selector when :all # ignore conditions on :all return find_all if selector == :all when :first # no conditions given, return the first record return self.new(1, *@data[0]) if args.size == 1 conditions = args[1][:conditions] raise TypeError.new("#{self}.find failed!\nArguments: #{args.inspect}") unless conditions.kind_of?(Hash) && conditions.size == 1 compare_col_nr = get_columns[conditions.keys[0]] raise "Unknown column :#{conditions.keys[0]}" unless compare_col_nr @data.each_with_index do |datum, i| # some special handling to integers cond_compare = if datum[compare_col_nr].kind_of?(Integer) conditions.values[0].to_i else # leave anything else as it is conditions.values[0] end return self.new(i + 1, *datum) if datum[compare_col_nr] == cond_compare end return nil when :last return self.new(@data.size, *@data[-1]) else # ignore conditions if id is given as the first argument return find_by_id(selector) if selector.kind_of?(Fixnum) end raise ArgumentError.new("#{self}.find failed!\nArguments: #{args.inspect}") end |
.first(*args) ⇒ Object
shortcut to #find(:first)
126 127 128 |
# File 'lib/constantrecord.rb', line 126 def self.first(*args) find(:first, *args) end |
.ids ⇒ Object
Returns an array of all ids
320 321 322 323 324 |
# File 'lib/constantrecord.rb', line 320 def self.ids ret = [] @data.length.times{|n| ret << n+1} ret end |
.last(*args) ⇒ Object
shortcut to #find(:last)
131 132 133 |
# File 'lib/constantrecord.rb', line 131 def self.last(*args) find(:last, *args) end |
.logger ⇒ Object
Get the logger
327 328 329 |
# File 'lib/constantrecord.rb', line 327 def self.logger @@logger end |
.logger=(value) ⇒ Object
Set the logger; ConstantRecord will try to use the Rails logger, if it’s there. Otherwise an error will be raised; set your own logger by calling ConstantRecord::Base.logger = MyAwesomeLogger.new
334 335 336 |
# File 'lib/constantrecord.rb', line 334 def self.logger=(value) @@logger = value end |
.match(*args) ⇒ Object
Rails 3.0: this method is checked in ActiveRecord::Base.compute_type
172 173 174 |
# File 'lib/constantrecord.rb', line 172 def self.match(*args) true end |
.method_missing(symbol, *args) ⇒ Object
Handle find_by_xxx calls on the class
216 217 218 219 220 221 222 |
# File 'lib/constantrecord.rb', line 216 def self.method_missing(symbol, *args) #:nodoc: if /^find_by_([_a-zA-Z]\w*)$/ =~ (symbol.to_s) return find(:first, :conditions => {$1.to_sym => args[0]}) end self.log(:debug, "#{self}::method_missing(:#{symbol})") super symbol, *args end |
.names ⇒ Object
Returns an array of the first column of your data. This method will be removed, if you override your class with columns, that do not include a column called :name
315 316 317 |
# File 'lib/constantrecord.rb', line 315 def self.names @data.map(&:first) end |
.options_for_select(options = {}) ⇒ Object
Creates options for a select box in a form. The result is basically the same as the following code with ActiveRecord:
MyActiveRecord.find(:all).collect{|obj| [obj.name, obj.id]}
Usage
With the class:
class Currency < ConstantRecord::Base
columns :name, :description
data ['EUR', 'Euro'],
['USD', 'US Dollar']
end
The following erb code:
<%= f.select :currency_id, Currency.options_for_select %>
Results to:
<select id="invoice_currency_id" name="invoice[currency_id]">
<option value="1">EUR</option>
<option value="2">USD</option>
</select>
While:
<%= f.select :currency_id, Currency.options_for_select(
:display => Proc.new { |obj| "#{obj.name} (#{obj.description})" },
:value => :name, :include_null => true,
:null_text => 'Please choose one', :null_value => nil ) %>
Results to:
<select id="invoice_currency_id" name="invoice[currency_id]">
<option value="">Please choose one</option>
<option value="EUR">EUR (Euro)</option>
<option value="USD">USD (US Dollar)</option>
</select>
Options
- :display
-
The attribute to call to display the text in the select box or a Proc object.
- :value
-
The value to use for the option value. Default is the id of the record.
- :include_null
-
Make an entry with the value 0 in the selectbox. Default is
false. - :null_text
-
The text to show with on value 0. Default is ‘-’.
- :null_value
-
The value of the null option. Default is 0.
284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 |
# File 'lib/constantrecord.rb', line 284 def self.( = {}) display = [:display] || get_columns.invert[0] raise "#{self}.options_for_select: :display must be either Symbol or Proc." unless display.kind_of?(Symbol) ||display.kind_of?(Proc) if display.kind_of?(Symbol) display_col_nr = get_columns[display] raise "Unknown column :#{display}" unless display_col_nr end value = [:value] || :id i = 0 result = @data.collect do |datum| i += 1 obj = self.new(i, *datum) option_show = display.kind_of?(Symbol) ? datum[display_col_nr] : display.call(obj) option_value = value == :id ? i : obj.send(value) [option_show, option_value] end if [:include_null] == true result.unshift [ [:null_text] || '-', .key?(:null_value) ? [:null_value] : 0 ] end result end |
.respond_to?(symbol) ⇒ Boolean
Keep this to spot problems in integration with ActiveRecord
225 226 227 228 229 |
# File 'lib/constantrecord.rb', line 225 def self.respond_to?(symbol) #:nodoc: result = super symbol self.log(:debug, "#{self}::respond_to?(:#{symbol}) => #{result}") if !result result end |
.table ⇒ Object
Show output in the form of ‘SELECT * FROM tablename;`
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 |
# File 'lib/constantrecord.rb', line 177 def self.table # get columns in the form of {0 => :id, 1 => :name, ...} cols = {:id => 0}.merge(Hash[*(get_columns.collect{|col_name, index| [col_name, index + 1]}.flatten)]).invert.sort # calculate the maximum width of each column max_size = [] cols.each do |index, name| woci = width_of_column(index) max_size << (woci > name.to_s.length ? woci : name.to_s.length) end output = '' # build table header output += '+-' + max_size.collect{|o| '-' * o}.join('-+-') + "-+\n" output += '| ' + cols.collect{|o| o[1].to_s.ljust(max_size[o[0]])}.join(' | ') + " |\n" output += '+-' + max_size.collect{|o| '-' * o}.join('-+-') + "-+\n" # build table data @data.each_with_index do |row, row_number| output += '| ' + (row_number + 1).to_s.ljust(max_size[0]) + ' | ' index = 0 output += row.collect{|o| index += 1; o.to_s.ljust(max_size[index])}.join(' | ') + " |\n" end output += '+-' + max_size.collect{|o| '-' * o}.join('-+-') + "-+\n" end |
Instance Method Details
#[](attr) ⇒ Object
152 153 154 |
# File 'lib/constantrecord.rb', line 152 def [](attr) instance_variable_get("@#{attr}") end |
#destroyed? ⇒ Boolean
A ConstantRecord will never be destroyed
167 168 169 |
# File 'lib/constantrecord.rb', line 167 def destroyed? #:nodoc: false end |
#empty? ⇒ Boolean
A ConstantRecord should never be empty
162 163 164 |
# File 'lib/constantrecord.rb', line 162 def empty? #:nodoc: false end |
#new_record? ⇒ Boolean
A ConstantRecord will never be a new record
157 158 159 |
# File 'lib/constantrecord.rb', line 157 def new_record? #:nodoc: false end |
#respond_to?(symbol) ⇒ Boolean
Keep this to spot problems in integration with ActiveRecord
209 210 211 212 213 |
# File 'lib/constantrecord.rb', line 209 def respond_to?(symbol) #:nodoc: result = super(symbol) self.class.log(:debug, "#{self.class}#respond_to?(:#{symbol}) => #{result}") if !result result end |