Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails table_name_prefix missing

I have got the following dir structure

models/foo/setting.rb
models/foo.rb

foo.rb content

 module Foo
  def self.table_name_prefix
    'foo_'
  end
 end

and setting.rb content

class Foo::Setting < ActiveRecord::Base
end

As soon as I am calling Foo::Setting.find… I am getting an error SQLException: no such table: settings which is indeed correct because the table is named foo_settings so rails seems to ignore the table prefix specified for the module Foo.

What can I do so that rails considers the prefix?

like image 236
gorootde Avatar asked Jan 18 '12 13:01

gorootde


2 Answers

You've define a method inside a module (Foo). This doesn't magically define that method on a class nested in that module.

I'd try something like

class Foo < ActiveRecord::Base   self.abstract_class = true   self.table_name_prefix = 'foo_' end 

And then inherit from Foo

class Foo::Setting < Foo ... end 
like image 168
Frederick Cheung Avatar answered Sep 29 '22 13:09

Frederick Cheung


This is probably caused by rails' autoloader. When doing this :

module Foo
  class Bar
  end
end

And then trying to use Foo::Bar, the autoloader first tries to locate app/models/foo/bar.rb. The file is loaded, and module Foo is defined here (albeit as a module containing solely Bar) so the autoloader never attempts to load app/models/foo.rb.

This should only happen in development mode, as in production mode all of your files are require'd on startup.

There are two workarounds AFAIK :

Cheat the autoloader

declare your class using class Foo::Bar, to force the autoloader to resolve a constant lookup for Foo.

This has the annoying side effect that the constant lookup inside Bar will NOT be scoped inside Foo, for instance :

# app/models/foo.rb
module Foo
 BAZ = "baz"
end

# app/models/foo/bar.rb
class Foo::Bar
  def baz
    BAZ
  end
end

here, Foo::Bar.new.bazwill fail, unless you reference the constant using Foo::BAZ. This can get really a mess when defining ActiveRecord associations, for instance.

Require the module

using require_dependency :

require_dependency 'foo'
module Foo
  class Bar
  end
end

This is IMHO the right solution, as it does not break the constant lookup, but it is also a bit annoying as you have to add the require statement on top of each namespaced file.

Note :

This bug seems to have been resolved in rails 4. I used the second workaround a lot while on rails 3, but I've tried to reproduce the bug in rails 4 and it does not show up anymore. I think they modified the way the autoloader works... For more info, see the rails guides on autoloading and reloading constants

like image 23
m_x Avatar answered Sep 29 '22 15:09

m_x