3

I have a Rails 3.1 app with the following 2 models

class Listing < ActiveRecord::Base
  has_many :listing_saves
end

class Team < ActiveRecord::Base
  has_many :listing_saves
  has_many :saved_listings, through: :listing_saves, source: 'listing'
end

The Join model looks like this

class ListingSave < ActiveRecord::Base
  belongs_to :team
  belongs_to :listing
end

Mow I think that there is an inflection problem because whenever I try to run my tests I get the following error (this is an example of an error and the test that caused it)

it "should return the listing saves associated with the team" do
  save = Factory :listing_save, listing: @listing, saver: @user, team: @team
  @team.listing_saves.should include save
end

Failures:

  1) Team listing_saves associations should return the listing saves associated with the team
     Failure/Error: @team.listing_saves.should include save
     NameError:
       uninitialized constant Team::ListingSafe
     # ./spec/models/team_spec.rb:55:in `block (3 levels) in <top (required)>'

as if Rails is singularizing listing_saves into listing_safe

Here are some custom inflectors I have tried (not all at the same time) (none of them work)

# config/initializers/inflections.rb
ActiveSupport::Inflector.inflections do |inflect|
  inflect.plural 'saved_listing', 'saved_listings'
  inflect.singular 'saved_listings', 'saved_listing'
  inflect.plural 'listing_save', 'listing_saves'
  inflect.singular 'listing_saves', 'listing_save'
  inflect.singular 'listing_safes', 'listing_safe'
  inflect.plural 'listing_safe', 'listing_safes'
  inflect.irregular 'listing_save', 'listing_saves'
  inflect.irregular 'saved_listing', 'saved_listings'
end

What can I do next?

Note: I found the this similar question but the answer doesn't seem to solve my problem

Edit I followed the answer below so that I now have the following in my config/initializers/inflections.rb

ActiveSupport::Inflector.inflections do |inflect|
  inflect.irregular 'listing_save', 'listing_saves'
end

When I open up a console session and run "listing saves".singularize I get "listing_save" as I would hope. However, it seems that at least part of my application doesn't get it, my tests still fail in the same way as before. (I swear I'm restarting my server and spork before I test/run the application!).

Edit 2 I wrote some tests for inflections in my app:

describe "inflection" do
  it "should singularize listing_saves properly" do
    "listing_saves".singularize.should == "listing_save"
  end

  it "should pluralize listing_save properly" do
    "listing_save".pluralize.should == "listing_saves"
  end
end

Now I have a situation where these tests pass fine, but other tests still fail with the same error I was having before

NameError:
       uninitialized constant User::ListingSafe

Same app, same spork instance, same files loaded. Something weird is going on here!??

TylerH
  • 20,799
  • 66
  • 75
  • 101
David Tuite
  • 22,258
  • 25
  • 106
  • 176

1 Answers1

11

You need to define an irregular inflection:

# Test your inflections!
> "listing_save".pluralize
=> "listing_saves" # OK!
> "listing_saves".singularize
=> "listing_safe"  # Ouch :(

# Make it smarter
ActiveSupport::Inflector.inflections { |i| 
  i.irregular 'listing_save', 'listing_saves' 
}

# Test again
> "listing_saves".singularize
=> "listing_save"  # Yay!

Ruby docs:

------------------------ ActiveSupport::Inflector::Inflections#irregular
     irregular(singular, plural)
------------------------------------------------------------------------
     Specifies a new irregular that applies to both pluralization and
     singularization at the same time. This can only be used for
     strings, not regular expressions. You simply pass the irregular in
     singular and plural form.

     Examples:

       irregular 'octopus', 'octopi'
       irregular 'person', 'people'

Edit:

Some further investigation - and it looks like others have stumbled upon this same problem also (inflections not working as expected with associations). So in the meantime you can set the class name manually:

has_many :listing_saves, :class_name => "ListingSave"

Someone else with the same problem, and an additional inflections tweak. Personally I'd go with the :class_name setting instead though:

Issue with custom inflections in Ruby on Rails 3.0.3

Community
  • 1
  • 1
Casper
  • 33,403
  • 4
  • 84
  • 79
  • Hi, sorry for retracting my acceptance, I only partially tested your solution until today. Weirdly, it works in the console but not in tests or when I run the application. I've edited my OP with the new situation. – David Tuite Jul 08 '11 at 06:50
  • Hi..no problem. It's pretty likely that spork is not loading the inflections file. Run spork with `spork -d` to look what it loads, and/or add the inflections file into the spork preload section in `spec_helpers.rb`. Also make a test case that tests just the inflection. It looks like you need one for that! :) – Casper Jul 08 '11 at 13:25
  • Very true about the tests! I wrote some and edited the OP again with the tests. The tests pass but I still the app doesn't work because of inflection issues. – David Tuite Jul 09 '11 at 16:41
  • Sorry it took so long to accept again. Didin't want to change my table names in the middle in introducing new features. It finaly worked with the `:class_name =>` setting. Thanks a lot! – David Tuite Jul 14 '11 at 17:07