Lighthouse has a new layout. Prefer the old one? Return to the old layout, and switch back any time from the link at the top of each page.

This project is archived and is in readonly mode.

[PATCH] AR migration generator includes model's modules in table name.

#4230

Below, the generated migration creates the table "my_module_posts". AR expects MyModule::Post to use a table named "posts".

After reading #1976 Scaffold generator not working well with namespaced resources and #2965 Advanced / foxy fixture features doesn't work well with models in modules, it seems AR's table name is the correct one.

Wheelie-Cyberman:~ $ rails --version
Rails 3.0.0.beta
Wheelie-Cyberman:~ $ rails blog
      create  
      create  README
      # ...
Wheelie-Cyberman:~ $ cd blog
Wheelie-Cyberman:~/blog $ rails g model my_module/post title:string body:text
      invoke  active_record
      create    db/migrate/20100319042749_create_my_module_posts.rb
      create    app/models/my_module/post.rb
      invoke    test_unit
      create      test/unit/my_module/post_test.rb
      create      test/fixtures/my_module_posts.yml
Wheelie-Cyberman:~/blog $ cat db/migrate/20100319042749_create_my_module_posts.rb 
class CreateMyModulePosts < ActiveRecord::Migration
  def self.up
    create_table :my_module_posts do |t|
      t.string :title
      t.text :body

      t.timestamps
    end
  end

  def self.down
    drop_table :my_module_posts
  end
end
Wheelie-Cyberman:~/blog $ rake db:migrate
(in /Users/phil/blog)
==  CreateMyModulePosts: migrating ============================================
-- create_table(:my_module_posts)
   -> 0.0015s
==  CreateMyModulePosts: migrated (0.0016s) ===================================

Wheelie-Cyberman:~/blog $ rails c
Loading development environment (Rails 3.0.0.beta)
>> MyModule::Post.all
ActiveRecord::StatementInvalid: SQLite3::SQLException: no such table: posts: SELECT     "posts".* FROM       "posts"
    from /opt/local/lib/ruby/gems/1.8/gems/activerecord-3.0.0.beta/lib/active_record/connection_adapters/abstract_adapter.rb:206:in `log'
    from /opt/local/lib/ruby/gems/1.8/gems/activerecord-3.0.0.beta/lib/active_record/connection_adapters/sqlite_adapter.rb:150:in `execute'
    from /opt/local/lib/ruby/gems/1.8/gems/activerecord-3.0.0.beta/lib/active_record/connection_adapters/sqlite_adapter.rb:390:in `catch_schema_changes'
    from /opt/local/lib/ruby/gems/1.8/gems/activerecord-3.0.0.beta/lib/active_record/connection_adapters/sqlite_adapter.rb:150:in `execute'
    from /opt/local/lib/ruby/gems/1.8/gems/activerecord-3.0.0.beta/lib/active_record/connection_adapters/sqlite_adapter.rb:293:in `select'
    from /opt/local/lib/ruby/gems/1.8/gems/activerecord-3.0.0.beta/lib/active_record/connection_adapters/abstract/database_statements.rb:7:in `select_all_without_query_cache'
    from /opt/local/lib/ruby/gems/1.8/gems/activerecord-3.0.0.beta/lib/active_record/connection_adapters/abstract/query_cache.rb:62:in `select_all'
    from /opt/local/lib/ruby/gems/1.8/gems/activerecord-3.0.0.beta/lib/active_record/base.rb:586:in `find_by_sql'
    from /opt/local/lib/ruby/gems/1.8/gems/activerecord-3.0.0.beta/lib/active_record/relation.rb:49:in `to_a'
    from /opt/local/lib/ruby/gems/1.8/gems/activerecord-3.0.0.beta/lib/active_record/relation/finder_methods.rb:119:in `all'
    from /opt/local/lib/ruby/gems/1.8/gems/activerecord-3.0.0.beta/lib/active_record/base.rb:560:in `__send__'
    from /opt/local/lib/ruby/gems/1.8/gems/activerecord-3.0.0.beta/lib/active_record/base.rb:560:in `all'
    from (irb):1

Reported by phs · March 19th, 2010 @ 05:00 AM

State: resolved
Milestone: 3.0.2
Assigned to: José Valim José Valim
Importance: High

Activity

  1. phs
    phs

    #4032 Module specific table_name_prefix looks like another issue stomping around in the same neighborhood.

    March 19th, 2010 @ 05:14 AM

  2. phs
    phs
    • Tag changed from activerecord module migration generator to activerecord, generator, migration, module, namespace

    To choose the new table's name, the migration generator template in AR at lib/generators/active_record/model/templates/migration.rb uses the (gasp) table_name method.

    table_name is defined over in railties:

    # lib/rails/generators/named_base.rb
    def table_name
      @table_name ||= begin
        base = pluralize_table_names? ? plural_name : singular_name
        (class_path + [base]).join('_')
      end
    end
    

    file_name, in the same file, looks like it would work.

    However, the other generator templates in AR also use table_name where one might expect. Given that, and the fact the method is named table_name, it seems more natural to override table_name in ActiveRecord::Generators::Base.

    March 19th, 2010 @ 07:55 AM

  3. phs
    phs
    • Tag changed from activerecord, generator, migration, module, namespace to activerecord, generator, migration, module, namespace, patch

    This patch effectively renames #table_name to #table_path, and provides a new #table_name that omits any leading namespace components.

    Most generators that use #table_name have been left alone, as they seem to work reasonably in either case. Migrations has been updated to keep the namespace components in their filenames (however, the names of the tables they manipulate have dropped their prefixes.) This keeps their tests happy, which seem to make a point of having the namespaced filenames in various situations.

    March 20th, 2010 @ 07:56 AM

  4. phs
    phs
    • Title changed from AR migration generator includes model's modules in table name. to [PATCH] AR migration generator includes model's modules in table name.

    March 20th, 2010 @ 07:57 AM

  5. phs
    phs

    Here's an alternate patch that makes the change to #table_name but doesn't bother introducing #table_path. Generated migrations from the model generator now make un-namespaced files.

    March 20th, 2010 @ 07:30 PM

  6. phs
    phs

    Here's a third option. This one leaves #table_name alone, and slips a self.table_name_prefix = "my_module_" when generating namespaced models.

    March 20th, 2010 @ 11:56 PM

  7. Francesc Esplugas
    Francesc Esplugas

    Same problem here. At this moment I'm fixing this problem by using "set_table_name". Using the table name prefix doesn't seem a good option:

    class Delayed::Job < ActiveRecord::Base
      self.table_name_prefix = 'delayed_'
    end
    
    rails_3b2 → rails console
    Loading development environment (Rails 3.0.0.beta2)
    >> Delayed::Job.table_name
    => "delayed_jobs"
    >> Post.table_name
    => "delayed_posts"
    
    rails_3b2 → rails console
    Loading development environment (Rails 3.0.0.beta2)
    >> Post.table_name
    => "posts"
    >> Delayed::Job.table_name
    => "delayed_jobs"
    >> Post.table_name
    => "posts"
    

    I would go for a set_table_name option ...

    April 8th, 2010 @ 07:51 AM

  8. Francesc Esplugas
    Francesc Esplugas

    Another observation is that the usage of self.table_name_prefix on a model would overwrite the system wide table_name_prefix option.

    April 8th, 2010 @ 07:56 AM

  9. José Valim
    José Valim
    • Milestone cleared.
    • Assigned user set to José Valim

    April 10th, 2010 @ 12:39 PM

  10. José Valim
    José Valim

    Can someone please provide a patch that changes self.table_name_prefix to use class_attribute instead of cattr_accessor allowing it to work with inheritance?

    April 10th, 2010 @ 12:41 PM

  11. phs
    phs

    #4032 Module specific table_name_prefix might be another way out. If we could find a canonical place to put the module-specific table_name_prefix declaration, then the model generator could ensure it is present.

    I don't have a justifiable opinion for preferring either #4032 Module specific table_name_prefix or class_attribute :table_name_prefix over the other, but the module-specific table_name_prefix is already in master.

    April 11th, 2010 @ 12:36 AM

  12. phs
  13. José Valim
    José Valim

    Awesome! I talked with Jeremy Kemper and he proposed us to follow the pattern in #4032 Module specific table_name_prefix. That said, when you run:

    rails g model my_module/post
    

    It should create a file in app/models/my_module.rb with the following contents:

    module MyModule
      def self.table_name_prefix
        'my_module_'
      end
    end
    

    Can you provide a patch for this? I will apply both this new patch and the class_attribute one once they are done. :)

    Thanks!

    April 11th, 2010 @ 06:40 AM

  14. Andrew White
    Andrew White

    José, should the patch try and load the parent constant and check for table_name_prefix or should it just check for the presence of the 'app/models/my_module.rb' file and don't create it if it already exists.

    The attached patch is a naive implementation that doesn't have any kind of intelligence. Is this the kind of thing you're looking for or a more sophisticated patch that checks for the parent constant first and then adjusts the migration name and the table name appropriately.

    The patch is just a proof of concept - if it's acceptable I'll add another later with docs and tests.

    April 11th, 2010 @ 09:33 AM

  15. José Valim
    José Valim

    Andrew, the patch looks great. We just need tests and there is no need to check if a file is already there, since Rails does it for us and delegates the decision to the user.

    April 11th, 2010 @ 10:24 AM

  16. Andrew White
  17. Andrew White
    Andrew White

    Forgot to squash commits - updated patch as single commit

    April 11th, 2010 @ 11:28 AM

  18. Andrew White
    Andrew White

    Third time lucky - removed check for existing file.

    April 11th, 2010 @ 01:03 PM

  19. Repository
  20. Repository
  21. José Valim
    José Valim

    Thanks guys, applied! Can someone please tell me if #2965 Advanced / foxy fixture features doesn't work well with models in modules is still an issue in Rails master?

    April 12th, 2010 @ 10:11 AM

  22. Andrew White
    Andrew White

    Yes, it's still an issue. Is it something you'd like me to investigate?

    April 12th, 2010 @ 02:34 PM

  23. José Valim
    José Valim

    @Andrew, if you can, it would be awesome!

    April 12th, 2010 @ 02:35 PM

  24. Andrew White
    Andrew White

    I'll get on it. One immediate consequence of getting it working is that the fixture file path will have to switch from matching the table name to matching the underscored class name - is this okay?

    April 12th, 2010 @ 02:51 PM

  25. Jeremy Kemper
    Jeremy Kemper
    • Milestone set to 3.0.2
    • Importance changed from to High

    October 15th, 2010 @ 11:01 PM