Reputation: 4073
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?
Upvotes: 28
Views: 18570
Reputation: 1084
Just create a base class in inside your namespaced model directory and require Foo in it, then extend your models from the base class.
Say I have app/models/foo.rb
module Foo
def self.table_name_prefix
'tble_prefix_'
end
end
Then in app/models/foo/base_record.rb
require_dependency 'foo'
module Foo
class BaseRecord < ActiveRecord::Base
self.abstract_class = true
end
end
Then extend from the BaseRecord
module Foo
class Bar < BaseRecord
end
end
Upvotes: 2
Reputation: 12554
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.baz
will 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
Upvotes: 11
Reputation: 2543
I had the same issue. Solved it by changing either of my application's namespace or the model's.
Take a look at this question. Using the same namespace for the application as for models causes to models not pick up the parent namespace table_name_prefix correctly.
Upvotes: 1
Reputation: 84114
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
Upvotes: 25