Commit f7a1b20d4dfae99665483b4ff862329bb0400c85
Committed by
Daniela Feitosa
1 parent
97c04098
Exists in
master
and in
29 other branches
Units of measurement are in the database now
- Product::UNITS was removed; and - We lost the power of gettext to translate units (ActionItem1859)
Showing
18 changed files
with
175 additions
and
44 deletions
Show diff stats
app/helpers/manage_products_helper.rb
| ... | ... | @@ -242,8 +242,7 @@ module ManageProductsHelper |
| 242 | 242 | end |
| 243 | 243 | |
| 244 | 244 | def select_unit(object) |
| 245 | - selected = object.unit.nil? ? '' : object.unit | |
| 246 | - select(object.class.name.downcase, 'unit', Product::UNITS.map{|unit| [_(unit[0]), unit[0]]}, {:selected => selected, :include_blank => _('Select the unit')}) | |
| 245 | + collection_select(object.class.name.downcase, :unit_id, environment.units, :id, :singular, {:include_blank => _('Select the unit')}) | |
| 247 | 246 | end |
| 248 | 247 | |
| 249 | 248 | def input_icon(input) |
| ... | ... | @@ -263,14 +262,13 @@ module ManageProductsHelper |
| 263 | 262 | if product_unit.blank? |
| 264 | 263 | _('Amount used in this product or service') |
| 265 | 264 | else |
| 266 | - _('Amount used by %s of this product or service') % _(product_unit) | |
| 265 | + _('Amount used by %s of this product or service') % product_unit.singular.downcase | |
| 267 | 266 | end |
| 268 | 267 | end |
| 269 | 268 | |
| 270 | 269 | def display_unit(input) |
| 271 | 270 | input_amount_used = content_tag('span', input.formatted_amount, :class => 'input-amount-used') |
| 272 | 271 | return input_amount_used if input.unit.blank? |
| 273 | - units = Product::UNITS.find {|unit| unit[0] == input.unit} | |
| 274 | - n_('1 %{singular_unit}', '%{num} %{plural_unit}', input.amount_used.to_f) % { :num => input_amount_used, :singular_unit => content_tag('span', units[0], :class => 'input-unit'), :plural_unit => content_tag('span', units[1], :class => 'input-unit') } | |
| 272 | + n_('1 %{singular_unit}', '%{num} %{plural_unit}', input.amount_used.to_f) % { :num => input_amount_used, :singular_unit => content_tag('span', input.unit.singular, :class => 'input-unit'), :plural_unit => content_tag('span', input.unit.plural, :class => 'input-unit') } | |
| 275 | 273 | end |
| 276 | 274 | end | ... | ... |
app/models/environment.rb
app/models/input.rb
app/models/product.rb
| ... | ... | @@ -42,14 +42,9 @@ class Product < ActiveRecord::Base |
| 42 | 42 | |
| 43 | 43 | acts_as_mappable |
| 44 | 44 | |
| 45 | - include FloatHelper | |
| 45 | + belongs_to :unit | |
| 46 | 46 | |
| 47 | - UNITS = [ | |
| 48 | - [N_('unit'), _('units')], | |
| 49 | - [N_('litre'), _('litres')], | |
| 50 | - [N_('kilo'), _('kilos')], | |
| 51 | - [N_('meter'), _('meters')], | |
| 52 | - ] | |
| 47 | + include FloatHelper | |
| 53 | 48 | |
| 54 | 49 | include WhiteListFilter |
| 55 | 50 | filter_iframes :description, :whitelist => lambda { enterprise && enterprise.environment && enterprise.environment.trusted_sites_for_iframe } |
| ... | ... | @@ -151,7 +146,7 @@ class Product < ActiveRecord::Base |
| 151 | 146 | end |
| 152 | 147 | |
| 153 | 148 | def name_with_unit |
| 154 | - unit.blank? ? name : "#{name} - #{_(unit)}" | |
| 149 | + unit.blank? ? name : "#{name} - #{unit.name.downcase}" | |
| 155 | 150 | end |
| 156 | 151 | |
| 157 | 152 | end | ... | ... |
| ... | ... | @@ -0,0 +1,17 @@ |
| 1 | +class Unit < ActiveRecord::Base | |
| 2 | + | |
| 3 | + validates_presence_of :singular | |
| 4 | + validates_presence_of :plural | |
| 5 | + | |
| 6 | + belongs_to :environment | |
| 7 | + validates_presence_of :environment_id | |
| 8 | + acts_as_list :scope => :environment | |
| 9 | + | |
| 10 | + def name | |
| 11 | + self.singular | |
| 12 | + end | |
| 13 | + def name=(value) | |
| 14 | + self.singular = value | |
| 15 | + end | |
| 16 | + | |
| 17 | +end | ... | ... |
db/migrate/20110221195242_create_units_and_add_reference_to_it_at_products_and_inputs.rb
0 → 100644
| ... | ... | @@ -0,0 +1,26 @@ |
| 1 | +class CreateUnitsAndAddReferenceToItAtProductsAndInputs < ActiveRecord::Migration | |
| 2 | + def self.up | |
| 3 | + create_table :units do |t| | |
| 4 | + t.string :singular, :null => false | |
| 5 | + t.string :plural, :null => false | |
| 6 | + t.integer :position | |
| 7 | + t.references :environment, :null => false | |
| 8 | + end | |
| 9 | + [:products, :inputs].each do |table_name| | |
| 10 | + change_table table_name do |t| | |
| 11 | + t.remove :unit | |
| 12 | + t.references :unit | |
| 13 | + end | |
| 14 | + end | |
| 15 | + end | |
| 16 | + | |
| 17 | + def self.down | |
| 18 | + drop_table :units | |
| 19 | + [:products, :inputs].each do |table_name| | |
| 20 | + change_table table_name do |t| | |
| 21 | + t.string :unit | |
| 22 | + t.remove_references :unit | |
| 23 | + end | |
| 24 | + end | |
| 25 | + end | |
| 26 | +end | ... | ... |
db/schema.rb
| ... | ... | @@ -9,7 +9,7 @@ |
| 9 | 9 | # |
| 10 | 10 | # It's strongly recommended to check this file into your version control system. |
| 11 | 11 | |
| 12 | -ActiveRecord::Schema.define(:version => 20110215153624) do | |
| 12 | +ActiveRecord::Schema.define(:version => 20110221195242) do | |
| 13 | 13 | |
| 14 | 14 | create_table "action_tracker", :force => true do |t| |
| 15 | 15 | t.integer "user_id" |
| ... | ... | @@ -289,11 +289,11 @@ ActiveRecord::Schema.define(:version => 20110215153624) do |
| 289 | 289 | t.datetime "created_at" |
| 290 | 290 | t.datetime "updated_at" |
| 291 | 291 | t.integer "position" |
| 292 | - t.string "unit" | |
| 293 | 292 | t.decimal "price_per_unit" |
| 294 | 293 | t.decimal "amount_used" |
| 295 | 294 | t.boolean "relevant_to_price", :default => true |
| 296 | 295 | t.boolean "is_from_solidarity_economy", :default => false |
| 296 | + t.integer "unit_id" | |
| 297 | 297 | end |
| 298 | 298 | |
| 299 | 299 | create_table "mailing_sents", :force => true do |t| |
| ... | ... | @@ -345,10 +345,10 @@ ActiveRecord::Schema.define(:version => 20110215153624) do |
| 345 | 345 | t.datetime "updated_at" |
| 346 | 346 | t.float "lat" |
| 347 | 347 | t.float "lng" |
| 348 | - t.string "unit" | |
| 349 | 348 | t.float "discount" |
| 350 | 349 | t.boolean "available", :default => true |
| 351 | 350 | t.boolean "highlighted" |
| 351 | + t.integer "unit_id" | |
| 352 | 352 | end |
| 353 | 353 | |
| 354 | 354 | add_index "products", ["enterprise_id"], :name => "index_products_on_enterprise_id" |
| ... | ... | @@ -469,6 +469,13 @@ ActiveRecord::Schema.define(:version => 20110215153624) do |
| 469 | 469 | t.string "thumbnail" |
| 470 | 470 | end |
| 471 | 471 | |
| 472 | + create_table "units", :force => true do |t| | |
| 473 | + t.string "singular", :null => false | |
| 474 | + t.string "plural", :null => false | |
| 475 | + t.integer "position" | |
| 476 | + t.integer "environment_id", :null => false | |
| 477 | + end | |
| 478 | + | |
| 472 | 479 | create_table "users", :force => true do |t| |
| 473 | 480 | t.string "login" |
| 474 | 481 | t.string "email" | ... | ... |
features/manage_inputs.feature
| ... | ... | @@ -20,6 +20,10 @@ Feature: manage inputs |
| 20 | 20 | | owner | category | name | |
| 21 | 21 | | redemoinho | rock | Abbey Road | |
| 22 | 22 | And feature "disable_products_for_enterprises" is disabled on environment |
| 23 | + And the following units | |
| 24 | + | singular | plural | | |
| 25 | + | Meter | Meters | | |
| 26 | + | Litre | Litres | | |
| 23 | 27 | |
| 24 | 28 | @selenium |
| 25 | 29 | Scenario: add first input to a product |
| ... | ... | @@ -110,9 +114,9 @@ Feature: manage inputs |
| 110 | 114 | And I am logged in as "joaosilva" |
| 111 | 115 | When I go to Rede Moinho's page of product Abbey Road |
| 112 | 116 | And I follow "Inputs" |
| 113 | - And I should see "Music" | |
| 117 | + Then I should see "Music" | |
| 114 | 118 | When I follow "Click here to add price and the amount used" |
| 115 | - And I should see "Price ($)" | |
| 119 | + And I should see "Price" | |
| 116 | 120 | And I fill in "Price" with "10.50" |
| 117 | 121 | And I press "Save" |
| 118 | 122 | Then I should not see "Save" |
| ... | ... | @@ -126,11 +130,9 @@ Feature: manage inputs |
| 126 | 130 | When I go to Rede Moinho's page of product Abbey Road |
| 127 | 131 | And I follow "Inputs" |
| 128 | 132 | And I follow "Click here to add price and the amount used" |
| 129 | - Then I should see "Price ($)" | |
| 130 | - And I should not see "Price by meter ($)" | |
| 131 | - When I select "meter" | |
| 132 | - Then I should see "Price by meter ($)" | |
| 133 | - And I should not see "Price ($)" | |
| 133 | + And I should not see "Price by Meter ($)" | |
| 134 | + When I select "Meter" | |
| 135 | + Then I should see "Price by Meter ($)" | |
| 134 | 136 | |
| 135 | 137 | @selenium |
| 136 | 138 | Scenario: Save all price details of input |
| ... | ... | @@ -143,10 +145,10 @@ Feature: manage inputs |
| 143 | 145 | And I follow "Click here to add price and the amount used" |
| 144 | 146 | And I fill in "Amount used" with "2.5" |
| 145 | 147 | And I fill in "Price" with "11.50" |
| 146 | - And I select "meter" | |
| 148 | + And I select "Meter" | |
| 147 | 149 | And I press "Save" |
| 148 | 150 | Then I should see "2.5" |
| 149 | - And I should see "meter" | |
| 151 | + And I should see "Meter" | |
| 150 | 152 | And I should not see "$ 11.50" |
| 151 | 153 | |
| 152 | 154 | @selenium |
| ... | ... | @@ -160,17 +162,17 @@ Feature: manage inputs |
| 160 | 162 | And I follow "Click here to add price and the amount used" |
| 161 | 163 | And I fill in "Amount used" with "2.5" |
| 162 | 164 | And I fill in "Price" with "11.50" |
| 163 | - And I select "meter" | |
| 165 | + And I select "Meter" | |
| 164 | 166 | And I press "Save" |
| 165 | 167 | Then I should see "2.5" |
| 166 | - And I should see "meter" | |
| 168 | + And I should see "Meter" | |
| 167 | 169 | When I follow "Edit" within ".input-details" |
| 168 | 170 | And I fill in "Amount used" with "3.0" |
| 169 | 171 | And I fill in "Price" with "23.31" |
| 170 | - And I select "litre" | |
| 172 | + And I select "Litre" | |
| 171 | 173 | And I press "Save" |
| 172 | 174 | Then I should see "3" |
| 173 | - And I should see "litre" | |
| 175 | + And I should see "Litre" | |
| 174 | 176 | |
| 175 | 177 | @selenium |
| 176 | 178 | Scenario: Cancel edition of a input |
| ... | ... | @@ -192,7 +194,7 @@ Feature: manage inputs |
| 192 | 194 | Scenario: Cancel edition of an input then edit again |
| 193 | 195 | Given the following input |
| 194 | 196 | | product | category | price_per_unit | unit | |
| 195 | - | Abbey Road | music | 10.0 | unit | | |
| 197 | + | Abbey Road | music | 10.0 | Meter | | |
| 196 | 198 | And I am logged in as "joaosilva" |
| 197 | 199 | When I go to Rede Moinho's page of product Abbey Road |
| 198 | 200 | And I follow "Inputs" |
| ... | ... | @@ -200,7 +202,7 @@ Feature: manage inputs |
| 200 | 202 | And I follow "Cancel" |
| 201 | 203 | And I follow "Edit" within ".input-details" |
| 202 | 204 | Then I should see "Amount used" |
| 203 | - And I should see "Price by unit" | |
| 205 | + And I should see "Price by Meter" | |
| 204 | 206 | |
| 205 | 207 | @selenium |
| 206 | 208 | Scenario: remove input | ... | ... |
features/manage_products.feature
| ... | ... | @@ -467,11 +467,14 @@ Feature: manage products |
| 467 | 467 | And the following products |
| 468 | 468 | | owner | category | name | |
| 469 | 469 | | redemoinho | bicycle | Bike | |
| 470 | + And the following units | |
| 471 | + | singular | plural | | |
| 472 | + | Kilo | Kilos | | |
| 470 | 473 | And I am logged in as "joaosilva" |
| 471 | 474 | When I go to Rede Moinho's page of product Bike |
| 472 | 475 | And I follow "Edit name and unit" |
| 473 | 476 | And I fill in "product_name" with "Red bicycle" |
| 474 | - And I select "kilo" | |
| 477 | + And I select "Kilo" | |
| 475 | 478 | And I press "Save" |
| 476 | 479 | Then I should see "Red bicycle - kilo" |
| 477 | 480 | ... | ... |
features/step_definitions/noosfero_steps.rb
| ... | ... | @@ -121,7 +121,8 @@ Given /^the following inputs?$/ do |table| |
| 121 | 121 | data = item.dup |
| 122 | 122 | product = Product.find_by_name(data.delete("product")) |
| 123 | 123 | category = Category.find_by_slug(data.delete("category").to_slug) |
| 124 | - input = Input.create!(data.merge(:product => product, :product_category => category)) | |
| 124 | + unit = Unit.find_by_singular(data.delete("unit")) | |
| 125 | + input = Input.create!(data.merge(:product => product, :product_category => category, :unit => unit)) | |
| 125 | 126 | input.update_attributes!(:position => data['position']) |
| 126 | 127 | end |
| 127 | 128 | end |
| ... | ... | @@ -369,4 +370,8 @@ Given /^someone suggested the following article to be published$/ do |table| |
| 369 | 370 | end |
| 370 | 371 | end |
| 371 | 372 | |
| 372 | - | |
| 373 | +Given /^the following units?$/ do |table| | |
| 374 | + table.hashes.each do |row| | |
| 375 | + Unit.create!(row.merge(:environment_id => 1)) | |
| 376 | + end | |
| 377 | +end | ... | ... |
script/sample-products
| ... | ... | @@ -39,3 +39,10 @@ for certifier in CERTIFIERS |
| 39 | 39 | print '.' |
| 40 | 40 | end |
| 41 | 41 | puts ' done!' |
| 42 | + | |
| 43 | +print "Creating units: " | |
| 44 | +[['Litre', 'Litres'], ['Kilo', 'Kilos'], ['Meter', 'Meters']].each do |unit| | |
| 45 | + Unit.create!(:singular => unit[0], :plural => unit[1], :environment => environment) | |
| 46 | + print '.' | |
| 47 | +end | |
| 48 | +puts ' done!' | ... | ... |
test/factories.rb
| ... | ... | @@ -436,4 +436,12 @@ module Noosfero::Factory |
| 436 | 436 | { :title => name, :body => "my own comment", :article_id => 1 }.merge(params) |
| 437 | 437 | end |
| 438 | 438 | |
| 439 | + ############################################### | |
| 440 | + # Unit | |
| 441 | + ############################################### | |
| 442 | + | |
| 443 | + def defaults_for_unit | |
| 444 | + { :singular => 'Litre', :plural => 'Litres', :environment_id => 1 } | |
| 445 | + end | |
| 446 | + | |
| 439 | 447 | end | ... | ... |
test/functional/manage_products_controller_test.rb
| ... | ... | @@ -272,7 +272,7 @@ class ManageProductsControllerTest < Test::Unit::TestCase |
| 272 | 272 | end |
| 273 | 273 | |
| 274 | 274 | should 'show product price when showing product if unit was informed' do |
| 275 | - product = fast_create(Product, :name => 'test product', :price => 50.00, :unit => 'unit', :enterprise_id => @enterprise.id, :product_category_id => @product_category.id) | |
| 275 | + product = fast_create(Product, :name => 'test product', :price => 50.00, :unit_id => fast_create(Unit).id, :enterprise_id => @enterprise.id, :product_category_id => @product_category.id) | |
| 276 | 276 | get :show, :id => product.id, :profile => @enterprise.identifier |
| 277 | 277 | |
| 278 | 278 | assert_tag :tag => 'span', :attributes => { :class => 'field-name' }, :content => /Price:/ |
| ... | ... | @@ -280,7 +280,7 @@ class ManageProductsControllerTest < Test::Unit::TestCase |
| 280 | 280 | end |
| 281 | 281 | |
| 282 | 282 | should 'show product price when showing product if discount was informed' do |
| 283 | - product = fast_create(Product, :name => 'test product', :price => 50.00, :unit => 'unit', :discount => 3.50, :enterprise_id => @enterprise.id, :product_category_id => @product_category.id) | |
| 283 | + product = fast_create(Product, :name => 'test product', :price => 50.00, :unit_id => fast_create(Unit).id, :discount => 3.50, :enterprise_id => @enterprise.id, :product_category_id => @product_category.id) | |
| 284 | 284 | get :show, :id => product.id, :profile => @enterprise.identifier |
| 285 | 285 | |
| 286 | 286 | assert_tag :tag => 'span', :attributes => { :class => 'field-name' }, :content => /List price:/ | ... | ... |
test/unit/environment_test.rb
| ... | ... | @@ -1108,4 +1108,12 @@ class EnvironmentTest < Test::Unit::TestCase |
| 1108 | 1108 | assert_not_includes env.enabled_features.keys, 'feature3' |
| 1109 | 1109 | end |
| 1110 | 1110 | |
| 1111 | + should 'has a list of units ordered by position' do | |
| 1112 | + litre = Unit.create!(:singular => 'Litre', :plural => 'Litres', :environment => Environment.default) | |
| 1113 | + meter = Unit.create!(:singular => 'Meter', :plural => 'Meters', :environment => Environment.default) | |
| 1114 | + kilo = Unit.create!(:singular => 'Kilo', :plural => 'Kilo', :environment => Environment.default) | |
| 1115 | + litre.move_to_bottom | |
| 1116 | + assert_equal ["Meter", "Kilo", "Litre"], Environment.default.units.map(&:singular) | |
| 1117 | + end | |
| 1118 | + | |
| 1111 | 1119 | end | ... | ... |
test/unit/input_test.rb
| ... | ... | @@ -78,7 +78,7 @@ class InputTest < Test::Unit::TestCase |
| 78 | 78 | end |
| 79 | 79 | |
| 80 | 80 | should 'not have price details if only unit is filled' do |
| 81 | - input = Input.new(:unit => 'unit') | |
| 81 | + input = Input.new(:unit => Unit.new) | |
| 82 | 82 | assert !input.has_price_details? |
| 83 | 83 | end |
| 84 | 84 | |
| ... | ... | @@ -157,4 +157,9 @@ class InputTest < Test::Unit::TestCase |
| 157 | 157 | assert_equal '1.00', input.formatted_value(:price_per_unit) |
| 158 | 158 | end |
| 159 | 159 | |
| 160 | + should 'has relation with unit' do | |
| 161 | + input = Input.new | |
| 162 | + assert_kind_of Unit, input.build_unit | |
| 163 | + end | |
| 164 | + | |
| 160 | 165 | end | ... | ... |
test/unit/manage_products_helper_test.rb
| ... | ... | @@ -137,6 +137,18 @@ class ManageProductsHelperTest < Test::Unit::TestCase |
| 137 | 137 | assert_equal 'LINK', edit_ui_button('link to edit', {:action => 'add_input', :id => product.id}) |
| 138 | 138 | end |
| 139 | 139 | |
| 140 | + should 'show unit on label of amount selection' do | |
| 141 | + input = Input.new() | |
| 142 | + input.expects(:product).returns(Product.new(:unit => Unit.new(:singular => 'Meter'))) | |
| 143 | + assert_equal 'Amount used by meter of this product or service', label_amount_used(input) | |
| 144 | + end | |
| 145 | + | |
| 146 | + should 'not show unit on label of amount selection if product has no unit selected' do | |
| 147 | + input = Input.new() | |
| 148 | + input.expects(:product).returns(Product.new) | |
| 149 | + assert_equal 'Amount used in this product or service', label_amount_used(input) | |
| 150 | + end | |
| 151 | + | |
| 140 | 152 | protected |
| 141 | 153 | include NoosferoTestHelper |
| 142 | 154 | include ActionView::Helpers::TextHelper | ... | ... |
test/unit/product_test.rb
| ... | ... | @@ -295,11 +295,6 @@ class ProductTest < Test::Unit::TestCase |
| 295 | 295 | end |
| 296 | 296 | end |
| 297 | 297 | |
| 298 | - should 'has a list of units' do | |
| 299 | - assert_kind_of Array, Product::UNITS | |
| 300 | - assert_includes Product::UNITS.flatten, 'unit' | |
| 301 | - end | |
| 302 | - | |
| 303 | 298 | should 'test if name is blank' do |
| 304 | 299 | product = Product.new |
| 305 | 300 | assert product.name_is_blank? |
| ... | ... | @@ -309,7 +304,7 @@ class ProductTest < Test::Unit::TestCase |
| 309 | 304 | product = Product.new |
| 310 | 305 | assert !product.has_basic_info? |
| 311 | 306 | |
| 312 | - product = Product.new(:unit => 'unit') | |
| 307 | + product = Product.new(:unit => Unit.new) | |
| 313 | 308 | assert product.has_basic_info? |
| 314 | 309 | |
| 315 | 310 | product = Product.new(:price => 1) |
| ... | ... | @@ -348,8 +343,13 @@ class ProductTest < Test::Unit::TestCase |
| 348 | 343 | should 'format name with unit' do |
| 349 | 344 | product = Product.new(:name => "My product") |
| 350 | 345 | assert_equal "My product", product.name_with_unit |
| 351 | - product.unit = 'litre' | |
| 346 | + product.unit = Unit.new(:name => 'litre') | |
| 352 | 347 | assert_equal "My product - litre", product.name_with_unit |
| 353 | 348 | end |
| 354 | 349 | |
| 350 | + should 'have relation with unit' do | |
| 351 | + product = Product.new | |
| 352 | + assert_kind_of Unit, product.build_unit | |
| 353 | + end | |
| 354 | + | |
| 355 | 355 | end | ... | ... |
| ... | ... | @@ -0,0 +1,34 @@ |
| 1 | +require File.dirname(__FILE__) + '/../test_helper' | |
| 2 | + | |
| 3 | +class UnitTest < Test::Unit::TestCase | |
| 4 | + | |
| 5 | + should 'require singular name' do | |
| 6 | + unit = Unit.new; unit.valid? | |
| 7 | + assert_match /can't be blank/, unit.errors["singular"] | |
| 8 | + end | |
| 9 | + | |
| 10 | + should 'require plural name' do | |
| 11 | + unit = Unit.new; unit.valid? | |
| 12 | + assert_match /can't be blank/, unit.errors["plural"] | |
| 13 | + end | |
| 14 | + | |
| 15 | + should 'belongs and require an environment' do | |
| 16 | + unit = Unit.new; unit.valid? | |
| 17 | + assert_match /can't be blank/, unit.errors["environment_id"] | |
| 18 | + unit.environment = Environment.default; unit.valid? | |
| 19 | + assert_nil unit.errors["environment_id"] | |
| 20 | + end | |
| 21 | + | |
| 22 | + should 'increment position automatically' do | |
| 23 | + first = Unit.create!(:singular => 'Litre', :plural => 'Litres', :environment => Environment.default) | |
| 24 | + second = Unit.create!(:singular => 'Meter', :plural => 'Meters', :environment => Environment.default) | |
| 25 | + assert_equal 1, first.position | |
| 26 | + assert_equal 2, second.position | |
| 27 | + end | |
| 28 | + | |
| 29 | + should 'has an getter and setter alias to singular field' do | |
| 30 | + unit = Unit.new(:name => 'Litre') | |
| 31 | + assert_equal 'Litre', unit.singular | |
| 32 | + end | |
| 33 | + | |
| 34 | +end | ... | ... |