Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Already on GitHub? Sign in to your account

Rails 4.1.0 - 3.1.0 (and lower?): model (file) naming issue #9326

Closed
john-999 opened this Issue Feb 19, 2013 · 23 comments

Comments

Projects
None yet

Rails 4.1.0 and lower cannot handle "generator model file names" that include a single character which is enclosed by underscores.

Try this:

rails g model a_b_c_something name:string
rake db:migrate
Console: ABCSomething.count
=> NameError: uninitialized constant ABCSomething

Why this happens:
The file name of the generated model will be "a_b_c_something.rb". Rails does not seem to load it by itself.

To load it (and make the NameError disappear):

  • Either (in the console): "require" the file manually
  • Or: Change the file name to reflect the "underscore condition" mentioned in the intro (i.e. to something like "a_bc_something.rb") and the Class name accordingly (i.e. to "ABcSomething")

So Rails must be updated to load model files with names that match the above mentioned criteria

Edit:
I have done some more testing: The above procedure fails down to v.3.1.0 (and possibliy even lower - sorry, I ran into other problems preventing me to go testing even lower). 4.0.0.rc2, 4.0.0 and 4.1.0 are also affected.

Member

steveklabnik commented Feb 19, 2013

Interesting. rails g model ABCSomething generates

$ cat app/models/abc_something.rb 
class AbcSomething < ActiveRecord::Base
  attr_accessible :name
end

/cc @fxn

In Rails 2.3.8. script/generate model a_b_c_something name:string gives:

../db/migrate/20130219171306_create_a_b_c_somethings.rb

class CreateABCSomethings < ActiveRecord::Migration
  def self.up
    create_table :abc_somethings do |t|
      t.string :name

      t.timestamps
    end
  end

  def self.down
    drop_table :abc_somethings
  end
end

models/abc_something.rb

class ABCSomething < ActiveRecord::Base
end
Member

steveklabnik commented Feb 20, 2013

@rahul-tapali use three backticks for code. I've edited your comment to include them. Much better. 👍

Owner

fxn commented Feb 20, 2013

ACK, I'll have a look a it.

That would be greatly appreciated!
(It comes in really handy, when you need to generate everything automatically due to the scale of your project...)

In the meantime, for those who want to ensure that their automatically generated model names used in a "rails g model_name ..." command will work when calling the model later, this would be a way to correct any (currently) problematic model names:

# Assumption: model_name contain only single underscores
model_name, model_name_corrected = 'peaches_come_from_a_can_they_were_put_there_by_a_man_in_a_factory_down_town', ''
reg_exp1, reg_exp2 = Regexp.new('([^_]{2,})?((_[^_])+_)?(_?[^_]+)?', true), Regexp.new('(_)?([^_]_)', true)

model_name.scan(reg_exp1).each do |capture|
  model_name_corrected << capture[0] unless capture[0].nil?
  capture[1].scan(reg_exp2).each {|capt| model_name_corrected << capt[0] unless capt[0].nil?; model_name_corrected << capt[1].delete('_')} unless capture[1].nil?
  model_name_corrected << capture[3] unless capture[3].nil?
end; model_name_corrected

There's more:

The problem described in the OP also occurs with model names of this type (used with the rails g command):

r_pc_105_module

In this case, there is no single character which is enclosed by underscores, but a number.

This is how it went:

$ rails g model r_pc_105_module name:string
      invoke  active_record
      create    db/migrate/20130222175054_create_r_pc_105_modules.rb
      create    app/models/r_pc_105_module.rb
      invoke    test_unit
      create      test/unit/r_pc_105_module_test.rb
      create      test/fixtures/r_pc_105_modules.yml

$ rake db:migrate
==  CreateRPc105Modules: migrating ============================================
-- create_table(:r_pc_105_modules)
   -> 0.3035s
==  CreateRPc105Modules: migrated (0.3038s) ===================================

-> the generated MySQL table has the (correct) name: r_pc_105_modules

$ rails c
Loading development environment (Rails 3.2.12)
1.9.3p327 :001 > RPc105Module.count
NameError: uninitialized constant RPc105Module

1.9.3p327 :002 > require "r_pc_105_module.rb"
 => true

1.9.3p327 :003 > RPc105Module.count
ActiveRecord::StatementInvalid: Mysql2::Error: Table 'mydatabase_development.r_pc105_modules' doesn't exist: SHOW FULL FIELDS FROM `r_pc105_modules`
    from /home/tom/.rvm/gems/ruby-1.9.3-p327@rails3211/gems/activerecord-3.2.12/lib/active_record/connection_adapters/abstract_mysql_adapter.rb:243:in `query'
    from /home/tom/.rvm/gems/ruby-1.9.3-p327@rails3211/gems/activerecord-3.2.12/lib/active_record/connection_adapters/abstract_mysql_adapter.rb:243:in `block in execute'
    from /home/tom/.rvm/gems/ruby-1.9.3-p327@rails3211/gems/activerecord-3.2.12/lib/active_record/connection_adapters/abstract_adapter.rb:280:in `block in log'
    ...

-> ActiveRecord looks for a (different) table name: r_pc105_modules (compare with the generated one above)

I can confirm that in 4.0.0beta1, both model name types...

a_b_c_something

(containing: "any-single-letter")

r_pc_105_module

(containing: "any-number")

...generated using...

rails g model a_b_c_something name:string

...and...

rails g model r_pc_105_module name:string

...still produce the errors described.

Member

steveklabnik commented Feb 26, 2013

Thank you for checking with the beta!

Contributor

Crunch09 commented Mar 2, 2013

@fxn Hi, are you already working on a patch? Otherwise i would try to fix it.

Contributor

larrylv commented Mar 6, 2013

https://github.com/rails/rails/blob/master/activesupport/lib/active_support/inflector/methods.rb#L86

    # As a rule of thumb you can think of +underscore+ as the inverse of
    # +camelize+, though there are cases where that does not hold:
    #
    # 'SSLError'.underscore.camelize # => "SslError"

Is this the reason why this issue happened? underscore is not entirely inverse of camelize.

When generator generates the model a_b_c_something, its model name is 'a_b_c_something'.camelize. And it uses the name 'a_b_c_something'.pluralize as its table name, and generate the migration create_table :a_b_c_somethings.

But when querying, its table_name is 'ABCSomething'.underscore.pluralize, which is abc_somethings.

Just a guess, I didn't test if it's right.

Contributor

Crunch09 commented Mar 6, 2013

@larrylv Yes, thats also what i found out, it is looking for the wrong file and thats why the model is not loaded. But we can't really 'fix' underscore because e.g. JSON would be searched in a file named j_s_o_n.rb . In my opinion the best solution would be to prohibit creating filenames like this via a rails generator, as i said i would love to work on a patch. Any feedback from @fxn would be appreciated :)

Member

schneems commented Mar 28, 2013

The question stands: raise an error or update the lazy loader. It looks like a loader issue to me. Could have it try multiple variations after first failure? cc/ @fxn

@rahul-tapali suggested with his comment that in 2.3.8, the rails generator named everything just like what Rails tries to load later (= everything worked fine).

This suggests that somewhere between 2.3.8 and 3.2.12, only the naming procedure was changed (but not the loading procedure).

I'm not @fxn, but by my logic, if the naming procedure worked before, it can be made to work again (find and reverse the faulty code merge) - no need to change the loader; and raising an error would then not be the best solution.

Unfortunately, as a noob, I am not skilled enough to help any further...

Member

schneems commented Mar 29, 2013

I'm guessing if it was changed, it was to fix another bug, so likely reverting that change would open up another bug. It is worth looking into though.

Richard Schneeman
http://heroku.com
@schneems

Sent from the road

On Friday, March 29, 2013 at 3:49 AM, john-999 wrote:

@rahul-tapali (https://github.com/rahul-tapali) suggested with his comment that in 2.3.8, the rails generator named everything just like what Rails tries to load later (= everything worked fine).
This suggests that somewhere between 2.3.8 and 3.2.12, only the naming procedure was changed (but not the loading procedure).
I'm not @fxn (https://github.com/fxn), but by my logic, if the naming procedure worked before, it can be made to work again (find and reverse the faulty code merge) - no need to change the loader; and raising an error would then not be the best solution.
Unfortunately, as a noob, I am not skilled enough to help any further...


Reply to this email directly or view it on GitHub (#9326 (comment)).

More testing reveals: The issue was actually introduced with or below v.3.1.0. (Original post updated accordingly.)

I've tested this with Rails 4.0.0:

This issue is still a problem. (Original post updated accordingly.)

I have also tested this with Rails 4.0.1:

This issue is still a problem. (Original post updated accordingly.)

Member

robin850 commented Nov 23, 2013

For me, this is quite impossible to resolve. I thought that we could put a rescue block when trying to eager load a constant trying other combination of the path but the possibilities are almost infinite. For instance, if there is a ABCSomething model, the file could be a_b_c_something.rb, ab_c_something.rb, a_bc_something.rb and so on.

At the very least, it would be nice to check whether the given string is underscored (e.g. a_b_c_someting) and in this case check whether "underscoring" the camel-cased version of it, is equal to the given one. If it's not the case then we should either:

  • abort the generator and display a message
  • generate the file but display a warning (that the user should load the model) and define the self.table_name value but this solution seems to be a bit overkill

What do you guys think ?

@john-999 john-999 added the stale label Apr 23, 2014

Owner

rafaelfranca commented May 1, 2014

This issue has been automatically marked as stale because it has not been commented on for at least
three months.

The resources of the Rails team are limited, and so we are asking for your help.

If you can still reproduce this error on the 4-1-stable, 4-0-stable branches or on master,
please reply with all of the information you have about it in order to keep the issue open.

Thank you for all your contributions.

@john-999 john-999 changed the title from Rails 4.0.1 - 3.1.0 (and lower?): model (file) naming issue to Rails 4.1.0 - 3.1.0 (and lower?): model (file) naming issue May 1, 2014

john-999 commented May 1, 2014

Just tested: The issue remains unresolved (at least up to 4-1-stable).

@fxn fxn was assigned by rafaelfranca May 1, 2014

@rails-bot rails-bot added the stale label Aug 19, 2014

This issue has been automatically marked as stale because it has not been commented on for at least
three months.

The resources of the Rails team are limited, and so we are asking for your help.

If you can still reproduce this error on the 4-1-stable, 4-0-stable branches or on master,
please reply with all of the information you have about it in order to keep the issue open.

Thank you for all your contributions.

This issue has been automatically closed because of inactivity.

If you can still reproduce this error on the 4-1-stable, 4-0-stable branches or on master,
please reply with all of the information you have about it in order to keep the issue open.

Thank you for all your contributions.

@rails-bot rails-bot closed this Nov 19, 2014

I can reproduce with 4-2-stable

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment