Rails 3 Plugin - Active Record table_name_prefix - ruby-on-rails

Im having problem to use table_name_prefix on my projects. I have a main apllication in my project that have others applications as plugins, these plugins works like a subsystem from the main application.
To organize the tables on database of the subsystems I would like to use the table_name_prefix of the ActiveRecord Plugin.
If I put on init.rb of plugin the command config.active_record.table_name_prefix = "per_" the main application will not work because the ActiveRecord will try to find for "per_users" but the only thing I want is that only the Plugin on my main application use the prefix "per_".
I tried to create a rails folder at my plugin with the command above but the same problem occurs, all the application try to find for prefixed table name.
An alternative is use the set_table_name in the model of plugin, but its not good for me because Im developing subsystems as rails plugin and I dont want to change the models when put the subsystem at the main application.
Someone can help me?

To have each plugin with own prefix, for Rails 3, try organize Your models inside plugin in namespace:
class Foo::Bar < ActiveRecord::Base
...
end
module Foo
def self.table_name_prefix
'foo_'
end
end
This will works just inside the plugin without changing anything inside the main application.
Other approach is to use some main model and inherit it from others like that:
class Foo < ActiveRecord::Base
def self.table_name_prefix
'foo_'
end
end
class Bar < Foo
...
end
sometimes this approach is used to extend all models with extra features.
More information in Rails documentation here

Take a look at this question. I ran into the same problem, forgot my application's name (main module) had the same name as a namespace for my models.

Related

Make Rails autoloading/reloading follow dynamic includes

Context
I want to add some admin specific code to all models via concerns that are automatically included. I'm using the naming convention MyModel => MyModelAdmin and they're in the standard Rails directory app/models/concerns/my_model_admin.rb. Then I can glob over all of them and do MyModel.include(MyModelAdmin).
Issue
Dynamic includes work fine, but when changing the concern in development Rails doesn't reload it properly. In fact the concern seems to get removed.
Reproduction
app/models/my_model.rb
class MyModel
end
app/models/concerns/my_model_admin.rb
module MyModelAdmin
extend ActiveSupport::Concern
def say
"moo"
end
end
config/initializers/.rb
MyModel.include(MyModelAdmin)
So far so good, MyModel.new.say == "moo".
But now change say to "baa" and you get NoMethodError undefined method 'say'.
Notes
I tried a number of things that didn't help:
require_dependency
Model.class_eval "include ModelAdministration"
config.autoload_paths
Using another explicit concern in ApplicationModel with an included hook that includes the specific concern in each model.
ActiveSupport.on_load only triggered on Base not each model.
Does this mean Rails can only autoload using static scope? I guess Rails sees the concern change, knows the model has it included, reloads the model but the static model definition doesn't have the include so the concern goes missing and stops being tracked. Is there a way to force Rails to track dynamically included modules?

how to list of all models and include one common module

I'm working on a Rails 3 app. I wrote one module and want it accessible to all my models without using include in each one. Please help me do this.
Create a file config/initializers/your_module_name.rb:
class ActiveRecord::Base
include YourModule
end

Resolving Namespace conflicts between a class and a gem

In my Rails 2.3 app, I found that the problem emanates from namespace collisions between an existing ActiveRecord model and a gem I recently added.
Specifically, I was trying to add jammit support to the app. One of jammit's dependant gems require's 'platform', which introduces a Platform module into the app's namespace. However, I already have an AR class with that name, and renaming it will introduce a lot of additional work and possible bugs.
I was wondering if there's a relatively simple way (using ruby's metamagic or whatnot) to prevent this namespace collision without having to rename my class or alter the actual gem. Thanks.
EDIT:
Instead of renaming/wrapping the class Platform throughout my app, and since the module Platform is only required by one other gem, I resulted to forking both gems, renaming Platform to XPlatform (both for the original gem and the one that imports it), and rebuilding them both. That seemed to work [sigh].
if the conditions are unavoidable when you cannot change the name
try wrapping your activerecord class in a module
module YourModule
class Platform < Activerecord::Base
named_scope :your_scope, lambda {#your code here}
end
end
So the only change that you have to do is something like
YourModule::Platform.your_scope
At the top of the class before any actions, you could just make an alias.
NewPlatform = ActiveRecord::
And just use the alias in the action for that class to avoid namespace conflicts.

Reopen plugin model in main Rails application

A plugin provides a model called User. Is it possible to reopen it in my app?
If I create app/models/user.rb and try it there, the whole model is overridden and the original plugin methods are no longer available.
This is the only way I found so far:
# app/models/plugin_user.rb
class PluginUser
def self.load
User.class_eval do
# my code here
end
end
end
# plugin model:
class User
# ...
end
PluginUser.load
It would be nice if there was a way of doing this without modifying the plugin code. In this case it doesn't matter because the plugin is mine, but if I needed to do the same to another plugin I'd need to fork it.

How/When/Where to Extend Gem Classes (via class_eval and Modules) in Rails 3?

What is the recommended way to extend class behavior, via class_eval and modules (not by inheritance) if I want to extend a class buried in a Gem from a Rails 3 app?
An example is this:
I want to add the ability to create permalinks for tags and categories (through the ActsAsTaggableOn and ActsAsCategory gems).
They have defined Tag and Category models.
I want to basically do this:
Category.class_eval do
has_friendly_id :title
end
Tag.class_eval do
has_friendly_id :title
end
Even if there are other ways of adding this functionality that might be specific to the gem, what is the recommended way to add behavior to classes in a Rails 3 application like this?
I have a few other gems I've created that I want to do this to, such as a Configuration model and an Asset model. I would like to be able to add create an app/models/configuration.rb model class to my app, and it would act as if I just did class_eval.
Anyways, how is this supposed to work? I can't find anything that covers this from any of the current Rails 3 blogs/docs/gists.
I do this as follows, first add a file to config/initializers where you can require the files that contain your extensions:
# config/initializers/extensions.rb
require "#{Rails.root}/app/models/category.rb"
require "#{Rails.root}/app/models/tag.rb"
Then you can just re-open the classes and add whatever else you need:
# app/models/category.rb
class Category
has_friendly_id :title
end
Only downside is that the server has to be restarted for any changes to these files to take effect, not sure if there is a better way that would overcome that.
You can use rails_engine_decorator gem:
https://github.com/atd/rails_engine_decorators
Just add in your Gemfile:
gem 'rails_engine_decorator'
And user class_eval in your decorators:
/app/decorators/models/category_decorator.rb
/app/decorators/models/tag_decorator.rb
It works for me. I hope you find it useful!

Resources