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 ADDED
@@ -0,0 +1,6 @@
1
+ constantrecord.gemspec
2
+ lib/constantrecord.rb
3
+ test/constantrecord_test.rb
4
+ Manifest
5
+ Rakefile
6
+ README.rdoc
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
+