enumerate_by 0.4.2 → 0.4.3

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/CHANGELOG.rdoc CHANGED
@@ -1,5 +1,12 @@
1
1
  == master
2
2
 
3
+ == 0.4.3 / 2009-06-14
4
+
5
+ * Add support for looking up enumerators by their symbol equivalent
6
+ * Fix incompatibility with Ruby 1.9
7
+ * Fix equality / xml serialization not working for non-string enumerators
8
+ * Improve compatibility with the stable branch of Rails 2.3 [Michael Schuerig]
9
+
3
10
  == 0.4.2 / 2009-05-03
4
11
 
5
12
  * Fix bootstrapping without ids not working on update for certain database adapters
data/Rakefile CHANGED
@@ -5,7 +5,7 @@ require 'rake/contrib/sshpublisher'
5
5
 
6
6
  spec = Gem::Specification.new do |s|
7
7
  s.name = 'enumerate_by'
8
- s.version = '0.4.2'
8
+ s.version = '0.4.3'
9
9
  s.platform = Gem::Platform::RUBY
10
10
  s.summary = 'Adds support for declaring an ActiveRecord class as an enumeration'
11
11
  s.description = s.summary
@@ -53,7 +53,14 @@ Rake::RDocTask.new(:rdoc) do |rdoc|
53
53
  rdoc.options << '--line-numbers' << '--inline-source'
54
54
  rdoc.rdoc_files.include('README.rdoc', 'CHANGELOG.rdoc', 'LICENSE', 'lib/**/*.rb')
55
55
  end
56
-
56
+
57
+ desc 'Generate a gemspec file.'
58
+ task :gemspec do
59
+ File.open("#{spec.name}.gemspec", 'w') do |f|
60
+ f.write spec.to_ruby
61
+ end
62
+ end
63
+
57
64
  Rake::GemPackageTask.new(spec) do |p|
58
65
  p.gem_spec = spec
59
66
  p.need_tar = true
data/lib/enumerate_by.rb CHANGED
@@ -57,8 +57,7 @@ module EnumerateBy
57
57
  # == Associations
58
58
  #
59
59
  # When using enumerations together with +belongs_to+ associations, the
60
- # enumerator value can be used as a shortcut for assigning the
61
- # association.
60
+ # enumerator value can be used as a shortcut for assigning the association.
62
61
  #
63
62
  # In addition, the enumerator value is automatically used during
64
63
  # serialization (xml and json) of the associated record instead of the
@@ -126,7 +125,7 @@ module EnumerateBy
126
125
  # Color.find_by_enumerator('red') # => #<Color id: 1, name: "red">
127
126
  # Color.find_by_enumerator('invalid') # => nil
128
127
  def find_by_enumerator(enumerator)
129
- first(:conditions => {enumerator_attribute => enumerator})
128
+ first(:conditions => {enumerator_attribute => typecast_enumerator(enumerator)})
130
129
  end
131
130
 
132
131
  # Finds the record that is associated with the given enumerator. If no
@@ -140,7 +139,7 @@ module EnumerateBy
140
139
  #
141
140
  # To avoid raising an exception on invalid enumerators, use +find_by_enumerator+.
142
141
  def find_by_enumerator!(enumerator)
143
- find_by_enumerator(enumerator) || raise(ActiveRecord::RecordNotFound, "Couldn't find #{name} with #{enumerator_attribute} #{enumerator.inspect}")
142
+ find_by_enumerator(enumerator) || raise(ActiveRecord::RecordNotFound, "Couldn't find #{name} with #{enumerator_attribute} #{typecast_enumerator(enumerator).inspect}")
144
143
  end
145
144
  alias_method :[], :find_by_enumerator!
146
145
 
@@ -148,10 +147,10 @@ module EnumerateBy
148
147
  #
149
148
  # For example,
150
149
  #
151
- # Color.find_all_by_enumerator('red', 'green') # => [#<Color id: 1, name: "red">, #<Color id: 1, name: "green">]
152
- # Color.find_all_by_enumerator('invalid') # => []
150
+ # Color.find_all_by_enumerator(['red', 'green']) # => [#<Color id: 1, name: "red">, #<Color id: 1, name: "green">]
151
+ # Color.find_all_by_enumerator('invalid') # => []
153
152
  def find_all_by_enumerator(enumerators)
154
- all(:conditions => {enumerator_attribute => enumerators})
153
+ all(:conditions => {enumerator_attribute => typecast_enumerator(enumerators)})
155
154
  end
156
155
 
157
156
  # Finds records with the given enumerators. If no record is found for a
@@ -160,13 +159,14 @@ module EnumerateBy
160
159
  #
161
160
  # For Example,
162
161
  #
163
- # Color.find_all_by_enumerator!('red', 'green') # => [#<Color id: 1, name: "red">, #<Color id: 1, name: "green">]
162
+ # Color.find_all_by_enumerator!(['red', 'green']) # => [#<Color id: 1, name: "red">, #<Color id: 1, name: "green">]
164
163
  # Color.find_all_by_enumerator!('invalid') # => ActiveRecord::RecordNotFound: Couldn't find Color with name(s) "invalid"
165
164
  #
166
165
  # To avoid raising an exception on invalid enumerators, use +find_all_by_enumerator+.
167
166
  def find_all_by_enumerator!(enumerators)
167
+ enumerators = [enumerators].flatten
168
168
  records = find_all_by_enumerator(enumerators)
169
- missing = [enumerators].flatten - records.map(&:enumerator)
169
+ missing = enumerators - records.map(&:enumerator)
170
170
  missing.empty? ? records : raise(ActiveRecord::RecordNotFound, "Couldn't find #{name} with #{enumerator_attribute}(s) #{missing.map(&:inspect).to_sentence}")
171
171
  end
172
172
 
@@ -178,9 +178,9 @@ module EnumerateBy
178
178
  [:find_by_sql, :exists?, :calculate].each do |method|
179
179
  define_method(method) do |*args|
180
180
  if EnumerateBy.perform_caching && perform_enumerator_caching
181
- enumerator_cache_store.fetch([method] + args) { super }
181
+ enumerator_cache_store.fetch([method] + args) { super(*args) }
182
182
  else
183
- super
183
+ super(*args)
184
184
  end
185
185
  end
186
186
  end
@@ -195,6 +195,20 @@ module EnumerateBy
195
195
  ensure
196
196
  self.perform_enumerator_caching = old
197
197
  end
198
+
199
+ private
200
+ # Typecasts the given enumerator to its actual value stored in the
201
+ # database. This will only convert symbols to strings. All other values
202
+ # will remain in the same type.
203
+ def typecast_enumerator(enumerator)
204
+ if enumerator.is_a?(Array)
205
+ enumerator.flatten!
206
+ enumerator.map! {|value| typecast_enumerator(value)}
207
+ enumerator
208
+ else
209
+ enumerator.is_a?(Symbol) ? enumerator.to_s : enumerator
210
+ end
211
+ end
198
212
  end
199
213
 
200
214
  module Bootstrapped
@@ -295,8 +309,8 @@ module EnumerateBy
295
309
  # * Dirty attributes
296
310
  #
297
311
  # Also note that records are created directly without creating instances
298
- # of the model. As a result, all of the attributes for the record must
299
- # be specified.
312
+ # of the model. As a result, all of the attributes for the record must be
313
+ # specified.
300
314
  #
301
315
  # This produces a significant performance increase when bootstrapping more
302
316
  # than several hundred records.
@@ -351,7 +365,7 @@ module EnumerateBy
351
365
  # a String, then it is compared against the enumerator. Otherwise,
352
366
  # ActiveRecord's default equality comparator is used.
353
367
  def ==(arg)
354
- arg.is_a?(String) ? self == self.class.find_by_enumerator!(arg) : super
368
+ arg.nil? || arg.is_a?(self.class) ? super : self == self.class.find_by_enumerator!(arg)
355
369
  end
356
370
 
357
371
  # Determines whether this enumeration is in the given list.
@@ -66,15 +66,15 @@ module EnumerateBy
66
66
  end
67
67
 
68
68
  # Sanitizes a hash of attribute/value pairs into SQL conditions for a WHERE clause.
69
- def sanitize_sql_hash_for_conditions_with_enumerations(attrs)
69
+ def sanitize_sql_hash_for_conditions_with_enumerations(attrs, *args)
70
70
  replace_enumerations_in_hash(attrs)
71
- sanitize_sql_hash_for_conditions_without_enumerations(attrs)
71
+ sanitize_sql_hash_for_conditions_without_enumerations(attrs, *args)
72
72
  end
73
73
 
74
74
  # Sanitizes a hash of attribute/value pairs into SQL conditions for a SET clause.
75
- def sanitize_sql_hash_for_assignment_with_enumerations(attrs)
75
+ def sanitize_sql_hash_for_assignment_with_enumerations(attrs, *args)
76
76
  replace_enumerations_in_hash(attrs, false)
77
- sanitize_sql_hash_for_assignment_without_enumerations(attrs)
77
+ sanitize_sql_hash_for_assignment_without_enumerations(attrs, *args)
78
78
  end
79
79
 
80
80
  # Make sure dynamic finders don't fail since it won't find the association
@@ -106,7 +106,7 @@ module EnumerateBy
106
106
  klass = reflection.klass
107
107
  attribute = reflection.primary_key_name
108
108
  id = if allow_multiple && enumerator.is_a?(Array)
109
- enumerator.map {|enumerator| klass.find_by_enumerator!(enumerator).id}
109
+ klass.find_all_by_enumerator!(enumerator).map(&:id)
110
110
  else
111
111
  klass.find_by_enumerator!(enumerator).id
112
112
  end
@@ -14,7 +14,21 @@ module EnumerateBy
14
14
  protected
15
15
  # Enumerator types are always strings
16
16
  def compute_type_with_enumerations
17
- enumeration_association? ? :string : compute_type_without_enumerations
17
+ if enumeration_association?
18
+ klass = @record.class.reflections[name.to_sym].klass
19
+ type = klass.columns_hash[klass.enumerator_attribute.to_s].type
20
+
21
+ case type
22
+ when :text
23
+ :string
24
+ when :time
25
+ :datetime
26
+ else
27
+ type
28
+ end
29
+ else
30
+ compute_type_without_enumerations
31
+ end
18
32
  end
19
33
 
20
34
  # Gets the real value representing the enumerator
@@ -0,0 +1,3 @@
1
+ class CarPart < ActiveRecord::Base
2
+ enumerate_by :number
3
+ end
@@ -0,0 +1,3 @@
1
+ class Order < ActiveRecord::Base
2
+ belongs_to :car_part
3
+ end
@@ -0,0 +1,12 @@
1
+ class CreateCarParts < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :car_parts do |t|
4
+ t.string :name
5
+ t.integer :number
6
+ end
7
+ end
8
+
9
+ def self.down
10
+ drop_table :car_parts
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ class CreateOrders < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :orders do |t|
4
+ t.string :state
5
+ t.references :car_part
6
+ end
7
+ end
8
+
9
+ def self.down
10
+ drop_table :orders
11
+ end
12
+ end
data/test/factory.rb CHANGED
@@ -40,9 +40,22 @@ module Factory
40
40
  )
41
41
  end
42
42
 
43
+ build CarPart do |attributes|
44
+ attributes.reverse_merge!(
45
+ :number => 123321
46
+ )
47
+ end
48
+
43
49
  build Color do |attributes|
44
50
  attributes.reverse_merge!(
45
51
  :name => 'red'
46
52
  )
47
53
  end
54
+
55
+ build Order do |attributes|
56
+ attributes[:car_part] = create_car_part unless attributes.include?(:car_part)
57
+ attributes.reverse_merge!(
58
+ :state => 'pending'
59
+ )
60
+ end
48
61
  end
@@ -23,7 +23,12 @@ class ModelWithBelongsToAssociationTest < ActiveRecord::TestCase
23
23
  end
24
24
 
25
25
  def test_should_use_nil_if_enumeration_does_not_exist
26
- @car.color = 'blue'
26
+ assert_nothing_raised { @car.color = 'blue' }
27
+ assert_nil @car.color
28
+ end
29
+
30
+ def test_should_allow_nil
31
+ assert_nothing_raised { @car.color = nil }
27
32
  assert_nil @car.color
28
33
  end
29
34
 
@@ -12,17 +12,49 @@ class EnumerationWithFinderConditionsTest < ActiveRecord::TestCase
12
12
  assert_equal @red_car, Car.find_by_color('red')
13
13
  end
14
14
 
15
+ def test_should_raise_exception_for_invalid_enumeration_in_dynamic_finders
16
+ assert_raise(ActiveRecord::RecordNotFound) { Car.find_by_color('invalid') }
17
+ end
18
+
19
+ def test_should_still_allow_non_enumeration_in_dynamic_finders
20
+ assert_equal @red_car, Car.find_by_id(@red_car.id)
21
+ end
22
+
15
23
  def test_should_replace_multiple_enumerations_in_dynamic_finders
16
24
  assert_equal [@red_car, @blue_car], Car.find_all_by_color(%w(red blue))
17
25
  end
18
26
 
27
+ def test_should_raise_exception_for_any_invalid_enumeration_in_dynamic_finders
28
+ assert_raise(ActiveRecord::RecordNotFound) { Car.find_all_by_color(%w(red invalid)) }
29
+ end
30
+
31
+ def test_should_still_allow_multiple_non_enumerations_in_dynamic_finders
32
+ assert_equal [@red_car, @blue_car], Car.find_all_by_id([@red_car.id, @blue_car.id])
33
+ end
34
+
19
35
  def test_should_replace_enumerations_in_find_conditions
20
36
  assert_equal @red_car, Car.first(:conditions => {:color => 'red'})
21
37
  end
22
38
 
39
+ def test_should_raise_exception_for_invalid_enumeration_in_find_conditions
40
+ assert_raise(ActiveRecord::RecordNotFound) { Car.first(:conditions => {:color => 'invalid'}) }
41
+ end
42
+
43
+ def test_should_still_allow_non_enumeration_in_find_conditions
44
+ assert_equal @red_car, Car.first(:conditions => {:id => @red_car.id})
45
+ end
46
+
23
47
  def test_should_replace_multiple_enumerations_in_find_conditions
24
48
  assert_equal [@red_car, @blue_car], Car.all(:conditions => {:color => %w(red blue)})
25
49
  end
50
+
51
+ def test_should_raise_exception_for_any_invalid_enumeration_in_find_conditions
52
+ assert_raise(ActiveRecord::RecordNotFound) { Car.all(:conditions => {:color => %w(red invalid)}) }
53
+ end
54
+
55
+ def test_should_still_allow_multiple_non_enumerations_in_find_conditions
56
+ assert_equal [@red_car, @blue_car], Car.all(:conditions => {:id => [@red_car.id, @blue_car.id]})
57
+ end
26
58
  end
27
59
 
28
60
  class EnumerationWithFinderUpdatesTest < ActiveRecord::TestCase
@@ -38,6 +70,16 @@ class EnumerationWithFinderUpdatesTest < ActiveRecord::TestCase
38
70
  assert_equal @blue, @red_car.color
39
71
  end
40
72
 
73
+ def test_should_raise_exception_for_invalid_enumeration_in_update_conditions
74
+ assert_raise(ActiveRecord::RecordNotFound) { Car.update_all({:color => 'invalid'}, :name => 'Ford Mustang') }
75
+ end
76
+
77
+ def test_should_still_allow_non_enumeration_in_update_conditions
78
+ Car.update_all({:color => 'blue'}, :id => @red_car.id)
79
+ @red_car.reload
80
+ assert_equal @blue, @red_car.color
81
+ end
82
+
41
83
  def test_should_not_replace_multiple_enumerations_in_update_conditions
42
84
  Car.update_all({:color => %w(red blue)}, :name => 'Ford Mustang')
43
85
  @red_car.reload
@@ -102,7 +102,8 @@ class EnumerationWithRecordsTest < ActiveRecord::TestCase
102
102
  end
103
103
 
104
104
  def test_should_raise_exception_for_invalid_index
105
- assert_raise(ActiveRecord::RecordNotFound) {Color['white']}
105
+ exception = assert_raise(ActiveRecord::RecordNotFound) {Color['white']}
106
+ assert_equal "Couldn't find Color with name \"white\"", exception.message
106
107
  end
107
108
 
108
109
  def test_should_allow_finding_all_by_enumerator
@@ -118,11 +119,63 @@ class EnumerationWithRecordsTest < ActiveRecord::TestCase
118
119
  end
119
120
 
120
121
  def test_should_raise_exception_find_finding_all_by_unknown_enumerator!
121
- assert_raise(ActiveRecord::RecordNotFound) { Color.find_all_by_enumerator!('invalid') }
122
+ exception = assert_raise(ActiveRecord::RecordNotFound) { Color.find_all_by_enumerator!('invalid') }
123
+ assert_equal "Couldn't find Color with name(s) \"invalid\"", exception.message
122
124
  end
123
125
 
124
126
  def test_should_raise_exception_if_only_some_found_when_finding_all_by_enumerator!
125
- assert_raise(ActiveRecord::RecordNotFound) { Color.find_all_by_enumerator!(['red', 'invalid']) }
127
+ exception = assert_raise(ActiveRecord::RecordNotFound) { Color.find_all_by_enumerator!(['red', 'invalid']) }
128
+ assert_equal "Couldn't find Color with name(s) \"invalid\"", exception.message
129
+ end
130
+ end
131
+
132
+ class EnumerationWithSymbolReferencesTest < ActiveRecord::TestCase
133
+ def setup
134
+ @red = create_color(:name => 'red')
135
+ @green = create_color(:name => 'green')
136
+ end
137
+
138
+ def test_should_index_by_enumerator
139
+ assert_equal @red, Color[:red]
140
+ end
141
+
142
+ def test_should_allow_finding_by_enumerator
143
+ assert_equal @red, Color.find_by_enumerator(:red)
144
+ end
145
+
146
+ def test_should_allow_finding_by_enumerator_with_nil
147
+ assert_nil Color.find_by_enumerator(nil)
148
+ end
149
+
150
+ def test_should_find_nothing_if_finding_by_unknown_enumerator
151
+ assert_nil Color.find_by_enumerator(:invalid)
152
+ end
153
+
154
+ def test_should_raise_exception_for_invalid_index
155
+ exception = assert_raise(ActiveRecord::RecordNotFound) {Color[:white]}
156
+ assert_equal "Couldn't find Color with name \"white\"", exception.message
157
+ end
158
+
159
+ def test_should_allow_finding_all_by_enumerator
160
+ assert_equal [@red, @green], Color.find_all_by_enumerator([:red, :green])
161
+ end
162
+
163
+ def test_should_allow_finding_all_by_enumerator_with_nil
164
+ assert_equal [], Color.find_all_by_enumerator(nil)
165
+ end
166
+
167
+ def test_should_find_nothing_if_finding_all_by_unknown_enumerator
168
+ assert_equal [], Color.find_all_by_enumerator(:invalid)
169
+ end
170
+
171
+ def test_should_raise_exception_find_finding_all_by_unknown_enumerator!
172
+ exception = assert_raise(ActiveRecord::RecordNotFound) { Color.find_all_by_enumerator!(:invalid) }
173
+ assert_equal "Couldn't find Color with name(s) \"invalid\"", exception.message
174
+ end
175
+
176
+ def test_should_raise_exception_if_only_some_found_when_finding_all_by_enumerator!
177
+ exception = assert_raise(ActiveRecord::RecordNotFound) { Color.find_all_by_enumerator!([:red, :invalid]) }
178
+ assert_equal "Couldn't find Color with name(s) \"invalid\"", exception.message
126
179
  end
127
180
  end
128
181
 
@@ -141,6 +194,10 @@ class EnumerationAfterBeingCreatedTest < ActiveRecord::TestCase
141
194
  assert @red == 'red'
142
195
  end
143
196
 
197
+ def test_should_allow_equality_with_symbol_enumerator
198
+ assert @red == :red
199
+ end
200
+
144
201
  def test_should_allow_equality_with_record
145
202
  assert @red == @red
146
203
  end
@@ -149,6 +206,10 @@ class EnumerationAfterBeingCreatedTest < ActiveRecord::TestCase
149
206
  assert 'red' == @red
150
207
  end
151
208
 
209
+ def test_should_allow_equality_with_nil
210
+ assert @red != nil
211
+ end
212
+
152
213
  def test_should_raise_exception_on_quality_with_invalid_enumerator
153
214
  assert_raise(ActiveRecord::RecordNotFound) {@red == 'invalid'}
154
215
  end
@@ -157,6 +218,10 @@ class EnumerationAfterBeingCreatedTest < ActiveRecord::TestCase
157
218
  assert @red.in?('red')
158
219
  end
159
220
 
221
+ def test_should_be_found_in_a_list_of_valid_symbol_names
222
+ assert @red.in?(:red)
223
+ end
224
+
160
225
  def test_should_not_be_found_in_a_list_of_invalid_names
161
226
  assert !@red.in?('blue', 'green')
162
227
  end
@@ -167,6 +232,47 @@ class EnumerationAfterBeingCreatedTest < ActiveRecord::TestCase
167
232
  end
168
233
  end
169
234
 
235
+ class EnumerationWithNumericEnumeratorAttributeTest < ActiveRecord::TestCase
236
+ def setup
237
+ @engine = create_car_part(:name => 'engine', :number => 111)
238
+ @radiator = create_car_part(:name => 'radiator', :number => 222)
239
+ @transmission = create_car_part(:name => 'transmission', :number => 333)
240
+ end
241
+
242
+ def test_should_have_an_enumerator
243
+ assert_equal 111, @engine.enumerator
244
+ end
245
+
246
+ def test_should_allow_equality_with_enumerator
247
+ assert @engine == 111
248
+ end
249
+
250
+ def test_should_allow_equality_with_record
251
+ assert @engine == @engine
252
+ end
253
+
254
+ def test_should_allow_equality_with_strings
255
+ assert '111' == @engine
256
+ end
257
+
258
+ def test_should_raise_exception_on_quality_with_invalid_enumerator
259
+ assert_raise(ActiveRecord::RecordNotFound) {@engine == 123}
260
+ end
261
+
262
+ def test_should_be_found_in_a_list_of_valid_names
263
+ assert @engine.in?(111)
264
+ end
265
+
266
+ def test_should_not_be_found_in_a_list_of_invalid_names
267
+ assert !@engine.in?(222, 333)
268
+ end
269
+
270
+ def test_should_stringify_enumerator
271
+ assert_equal '111', @engine.to_s
272
+ assert_equal '111', @engine.to_str
273
+ end
274
+ end
275
+
170
276
  class EnumerationWithCachingTest < ActiveRecord::TestCase
171
277
  def setup
172
278
  @red = create_color(:name => 'red')
@@ -69,3 +69,23 @@ class XmlSerializerTest < ActiveRecord::TestCase
69
69
  assert_equal expected, @car.to_xml
70
70
  end
71
71
  end
72
+
73
+ class XmlSerializerWithNumericEnumeratorAttributeTest < ActiveRecord::TestCase
74
+ def setup
75
+ @engine = create_car_part(:name => 'engine', :number => 123321)
76
+ @order = create_order(:state => 'pending', :car_part => @engine)
77
+ end
78
+
79
+ def test_should_be_able_to_convert_to_xml
80
+ expected = <<-eos
81
+ <?xml version="1.0" encoding="UTF-8"?>
82
+ <order>
83
+ <car-part type="integer">123321</car-part>
84
+ <id type="integer">#{@order.id}</id>
85
+ <state>pending</state>
86
+ </order>
87
+ eos
88
+
89
+ assert_equal expected, @order.to_xml
90
+ end
91
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: enumerate_by
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ version: 0.4.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aaron Pfeifer
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-05-03 00:00:00 -04:00
12
+ date: 2009-06-14 00:00:00 -04:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -40,12 +40,16 @@ files:
40
40
  - test/app_root
41
41
  - test/app_root/app
42
42
  - test/app_root/app/models
43
+ - test/app_root/app/models/order.rb
43
44
  - test/app_root/app/models/color.rb
44
45
  - test/app_root/app/models/car.rb
46
+ - test/app_root/app/models/car_part.rb
45
47
  - test/app_root/db
46
48
  - test/app_root/db/migrate
49
+ - test/app_root/db/migrate/003_create_car_parts.rb
47
50
  - test/app_root/db/migrate/001_create_colors.rb
48
51
  - test/app_root/db/migrate/002_create_cars.rb
52
+ - test/app_root/db/migrate/004_create_orders.rb
49
53
  - test/test_helper.rb
50
54
  - CHANGELOG.rdoc
51
55
  - init.rb