简体   繁体   中英

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...

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.

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

> "data".pluralize
"data"

So, your table should be named "funnel_data".

"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

在rails类名中,复数形式是表名称,所以funnel_data复数形式是funnel_data,因此无需更改表名称。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM