Orabîg
Orabîg

Reputation: 11992

How does Rails guess the table name from model?

I've messed up my rails database, and a little lost at that point. All started when I realized that one of my tables name wasn't ending with an 's like the others. (I really don't know why, because all my other tables are prefixed with an 's') So I tried to rename it and made a migration :

rename_table :funnel_data, :funnel_datas

For information, the corresponding model is called FunnelData :

class FunnelData < ActiveRecord::Base
   ...
end

So the migration seemed to do its job, and ran without errors.

But now, in the console, I got the following :

2.0.0-p247 :014 > FunnelData
 => FunnelData(Table doesn't exist)

I checked in my DB, and the table funnel_datas does exist !

So it leads to my question : how is Rails supposed to know the "new" name of the table ? How can I fix my situation ? Thanks.


Update : ok, now that I know taht "data" is the plural for "data", I rolled back my migration, and tried to make my way, but now I get a weird behaviour.

First, let's intruduce another class :

class FunnelStage < ActiveRecord::Base
    has_many :funnel_data
    (...)
end

And my console says :

2.0.0-p247 :046 > f = FunnelStage.first
  FunnelStage Load (0.3ms)  SELECT `funnel_stages`.* FROM `funnel_stages` ORDER BY `funnel_stages`.`id` ASC LIMIT 1
 => #<FunnelStage id: 1, name: "Inquiries", order: 100, created_at: "2013-09-14 23:08:55", updated_at: "2013-09-14 23:08:55">
2.0.0-p247 :047 > f.funnel_dat
f.funnel_data        f.funnel_data=       f.funnel_datum_ids   f.funnel_datum_ids=
2.0.0-p247 :047 > f.funnel_data
NameError: uninitialized constant FunnelStage::FunnelDatum
        from /usr/local/rvm/gems/ruby-2.0.0-p247@rails4test/gems/activerecord-4.0.0/lib/active_record/inheritance.rb:125:in `compute_type'
        from /usr/local/rvm/gems/ruby-2.0.0-p247@rails4test/gems/activerecord-4.0.0/lib/active_record/reflection.rb:178:in `klass'
        (...)
        from bin/rails:4:in `<main>'
2.0.0-p247 :048 > f.funnel_datum_ids
NameError: uninitialized constant FunnelStage::FunnelDatum
        from /usr/local/rvm/gems/ruby-2.0.0-p247@rails4test/gems/activerecord-4.0.0/lib/active_record/inheritance.rb:125:in `compute_type'
        from /usr/local/rvm/gems/ruby-2.0.0-p247@rails4test/gems/activerecord-4.0.0/lib/active_record/reflection.rb:178:in `klass'
        (...)
        from bin/rails:4:in `<main>'

So now, Rails is speaking latin ? (data/datum...)

Edit and answer : Ok, I figured it out by myself. Rails had difficulties to understand the association, because it tried to singularize the "funnel_data" to a brand new "funnel_datum" name (which would be correct btw)

So I had to write :

class FunnelStage < ActiveRecord::Base
    has_many :funnel_data, class_name: "FunnelData"
    (...)
end

to make it work.

Many thanks to all of you who helped me understanding that...

Upvotes: 1

Views: 3063

Answers (4)

stfcodes
stfcodes

Reputation: 1380

To fix your issue, just add: self.table_name = "funnel_datas" below your model definition.


Behind the scenes ActiveRecord uses the method #tableize. From the guides:

The method tableize is #underscore followed by #pluralize.

As a rule of thumb, tableize returns the table name that corresponds to a given model for simple cases. The actual implementation in Active Record is not straight tableize indeed, because it also demodulizes the class name and checks a few options that may affect the returned string.

Pluralize, by default uses common english inflections to get the plural form of the word, but "data" is plural. So:

> "FunnelData".underscore #=> "funnel_data"
> "funnel_data".pluralize #=> "funnel_data"

So your model looks for the "funnel_data" table by default.

Upvotes: 3

Oleg Haidul
Oleg Haidul

Reputation: 3732

"user".pluralize
=> "users"

But:

"data".pluralize
=> "data"

If u want to use funnel_datas table name:

class FunnelData < ActiveRecord::Base
  set_table_name "funnel_datas"
end

Upvotes: 1

Amar
Amar

Reputation: 6942

in rails class name plural is table name,so funnel_data plural is funnel_data so no need to change table name.

Upvotes: 0

kik
kik

Reputation: 7937

That's because "data" is an uncountable word and rails knows it :

> "data".pluralize
"data"

So, your table should be named "funnel_data".

Upvotes: 1

Related Questions