# Extending a Model that is in a plugin

**URL:** <https://www.ruby-forum.com/t/extending-a-model-that-is-in-a-plugin/184208>\
**Category:** Rails\
**Created:** [February 26, 2010, 6:35pm UTC](https://www.ruby-forum.com/t/extending-a-model-that-is-in-a-plugin/184208 "2010-02-26T18:35:54Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![yannimac](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/y/7993a0/32.png) [@yannimac](https://www.ruby-forum.com/u/yannimac)\
**Post date:** [February 26, 2010, 6:35pm UTC](https://www.ruby-forum.com/t/extending-a-model-that-is-in-a-plugin/184208/1 "2010-02-26T18:35:54Z")

</div>

I have several apps that share common base models which I am coding into  
a plugin, but each app may need to add some additional code or override  
some code in the plugin model.

One of the main differences is that I use multiple database servers in  
alot of these apps, which is managed by the “use\_db” plugin. I am  
trying to figure out a way to use the “use\_db” plugin without hard  
coding it into the plugin class. I dont want to have to change the  
plugin every time I install it in a new app.

Can anyone think of a way to create a class inside the rails directories  
that would be able to extend the plugin model and also be able to  
specify my “use\_db” database… overriding the default rails database.  
I would also need to be able to add new methods and override methods  
contained in the plugin model. The model in the plugin contains lots of  
associations, named\_scopes, etc… so that stuff would still need to be  
active in the extended model… so I dont think a module would work.

For those not familiar with “use\_db” it just allows you to include a  
prefix which is pulled from database.yml, and the model will use this  
database. Example:

class Widget \< ActiveRecord::Base  
use\_db :prefix =\> “slave2\_”  
end

this would use the database config “slave2\_production” in database.yml  
for that model if you are in prod mode.

I have tried using “extends” inside the class, creating a subclass,  
etc… but nothing seems to give me the behavior I desire. Any ideas  
guys? Thanks in advance!

---

<div class="post-metadata">

**Author:** ![yannimac](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/y/7993a0/32.png) [@yannimac](https://www.ruby-forum.com/u/yannimac)\
**Post date:** [March 6, 2010, 8:49pm UTC](https://www.ruby-forum.com/t/extending-a-model-that-is-in-a-plugin/184208/2 "2010-03-06T20:49:35Z")

</div>

I have the same issue. Have you been able to figure it out?

Thanks,  
Maher

---

<div class="post-metadata">

**Author:** ![yannimac](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/y/7993a0/32.png) [@yannimac](https://www.ruby-forum.com/u/yannimac)\
**Post date:** [March 8, 2010, 4:45am UTC](https://www.ruby-forum.com/t/extending-a-model-that-is-in-a-plugin/184208/3 "2010-03-08T04:45:18Z")

</div>

Maher Hawash wrote:

> I have the same issue. Have you been able to figure it out?
> 
> Thanks,  
> Maher

I moved on to other work after I posted this. I will probably revisit  
this week. I will let you know what I figure out. There has to be an  
elegant way to do this. I really just need to learn more about the  
object-oriented side of Ruby works… reading about it now.

---

<div class="post-metadata">

**Author:** ![yannimac](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/y/7993a0/32.png) [@yannimac](https://www.ruby-forum.com/u/yannimac)\
**Post date:** [March 8, 2010, 4:47pm UTC](https://www.ruby-forum.com/t/extending-a-model-that-is-in-a-plugin/184208/4 "2010-03-08T16:47:13Z")

</div>

Andy, thank you very much for the reply. If I can get the first  
solution to work, I think I would prefer that. I have been playing  
around with the code and I am getting errors saying my model class (in  
rails dir) should define Widget. So is it even possible to use Widget  
as the name in the plugin Base model and at the same time have a rails  
model with the same name using it as a subclass?

class Widget \< MyPlugin:: Widget::Base

I was thinking I could just rename the base class to BaseWidget, but  
then rails is looking for that database name (base\_widgets) when it  
loads widget since its an activerecord subclass.

Thanks for your help!

---

<div class="post-metadata">

**Author:** ![yannimac](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/y/7993a0/32.png) [@yannimac](https://www.ruby-forum.com/u/yannimac)\
**Post date:** [March 8, 2010, 5:10pm UTC](https://www.ruby-forum.com/t/extending-a-model-that-is-in-a-plugin/184208/5 "2010-03-08T17:10:16Z")

</div>

> Andy, thank you very much for the reply. If I can get the first  
> solution to work, I think I would prefer that. I have been playing  
> around with the code and I am getting errors saying my model class (in  
> rails dir) should define Widget.

This normally means that you have a file named “widget.rb” but don’t  
define  
a class called “Widget” in it. The class name/file name must match  
(except  
for the conventional conversion to camelcase from underscores) for Rails  
to  
be able to find/autoload it.

> So is it even possible to use Widget  
> as the name in the plugin Base model and at the same time have a rails  
> model with the same name using it as a subclass?

Yes.

You could even use the same class name, Ruby let’s you re-open a class  
and  
add new methods to it or change existing ones. But you can certainly  
have a  
base class declared in your plugin and have a specific class inherit  
from  
that in your app.

> class Widget \< MyPlugin:: Widget::Base
> 
> I was thinking I could just rename the base class to BaseWidget, but  
> then rails is looking for that database name (base\_widgets) when it  
> loads widget since its an activerecord subclass.

Oohhh that’s a good point. You may have to name your plugin class as  
MyPlugin::Widget as I don’t think ActiveRecord supports namespaced  
classes  
to tables out of the box (I remember adding code to a Rails project a  
while  
ago because I WANTED it to do that, but it may have changed by now).

However, from a quick play it seems that ActiveRecord doesn’t look for  
the  
database table unless you actually use it, and you shouldn’t be using  
your  
BaseWidget class but a subclass of it (correctly named to match the  
table).

> Thanks for your help!

No worries, keep posting back with what you have and what’s going wrong  
until it’s solved; I’m sure we’ll be able to get you running…

Cheers,

Andy

---

<div class="post-metadata">

**Author:** ![yannimac](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/y/7993a0/32.png) [@yannimac](https://www.ruby-forum.com/u/yannimac)\
**Post date:** [March 8, 2010, 10:11am UTC](https://www.ruby-forum.com/t/extending-a-model-that-is-in-a-plugin/184208/6 "2010-03-08T10:11:09Z")

</div>

On 26 February 2010 17:35, Yanni M. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> I have several apps that share common base models which I am coding into  
> a plugin, but each app may need to add some additional code or override  
> some code in the plugin model.

OK, so let’s assume your base model is like this:

class MyPlugin:: Widget::Base \< ActiveRecord::Base  
… some code …  
end

> One of the main differences is that I use multiple database servers in  
> alot of these apps, which is managed by the “use\_db” plugin. I am  
> trying to figure out a way to use the “use\_db” plugin without hard  
> coding it into the plugin class. I dont want to have to change the  
> plugin every time I install it in a new app.

OK, so then in your app you declare a model as:

class Widget \< MyPlugin:: Widget::Base  
use\_db :prefix =\> “slave2\_”  
end

Alternatively, if you want to declare a User class in your plugin and  
have  
your app use that if it’s found, why not just create an initializer in  
your  
application. As you can read here -  
[http://railsguts.com/initialization.html](http://railsguts.com/initialization.html) - plugins are loaded before  
application initializers, so you could put a file in your  
config/initializers folder that just does:

class Widget  
use\_db :prefix =\> “slave2\_”  
end

The Widget class could already have been defined from your plugin  
initializer, so you’re then just re-opening the class and adding your  
use\_db.

Can anyone think of a way to create a class inside the rails directories

> that would be able to extend the plugin model and also be able to  
> specify my “use\_db” database… overriding the default rails database.  
> I would also need to be able to add new methods and override methods  
> contained in the plugin model. The model in the plugin contains lots of  
> associations, named\_scopes, etc… so that stuff would still need to be  
> active in the extended model… so I dont think a module would work.

I’m not sure I follow you. However, you could do the above with the  
config/initializers to open your defined plugin class and add your  
functionality. If you want you could just do a simple require within  
the  
config/initializer/widget.rb file that loads the file from within  
app/models  
(which may be a better place for your modifications).

require Rails.root.join(“app”, “models”, “widget”)

The reason for this is that you can’t just re-open the class within  
app/models/widget.rb as that file will only be opened if the class isn’t  
defined (it’s an autoloading path, not an “open every file in this path  
at  
boot time” path), so you need to specifically load it from an  
initializer/environment file.

> I have tried using “extends” inside the class, creating a subclass,  
> etc… but nothing seems to give me the behavior I desire. Any ideas  
> guys?

If you can flesh out your requirement/desires a bit more fully I’ll  
happily  
work up a solution with you, but I’m going on guesswork a bit at the  
moment  
🙂

Cheers,

Andy

---

<div class="post-metadata">

**Author:** ![yannimac](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/y/7993a0/32.png) [@yannimac](https://www.ruby-forum.com/u/yannimac)\
**Post date:** [March 8, 2010, 6:16pm UTC](https://www.ruby-forum.com/t/extending-a-model-that-is-in-a-plugin/184208/7 "2010-03-08T18:16:06Z")

</div>

Additionally, you can include a default class in your plugin. This  
would give you the model out of the box when you install the plugin, so  
you don’t even have to create a model in /app/models/

#-----------------------------------------------------------

# /my\_rails\_app/vendor/plugins/my\_plugin/widget.rb

# ----------------------------------------------------------

class Widget \< ActiveRecord::Base  
include BaseWidget  
end

Then if you have additional functionality you need to add (like use\_db),  
you just drop a class into /my\_rails\_app/app/models/ and it will use  
that one instead of the default class that is contained in the plugin.

---

<div class="post-metadata">

**Author:** ![yannimac](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/y/7993a0/32.png) [@yannimac](https://www.ruby-forum.com/u/yannimac)\
**Post date:** [March 8, 2010, 6:05pm UTC](https://www.ruby-forum.com/t/extending-a-model-that-is-in-a-plugin/184208/8 "2010-03-08T18:05:44Z")

</div>

Andy, Thanks for all your responses. This helped me do some additional  
research. I found something that works perfectly for my scenario.  
Using mixin modules.

[http://weblog.jamisbuck.org/2007/1/17/concerns-in-activerecord](http://weblog.jamisbuck.org/2007/1/17/concerns-in-activerecord)

I tried using mixins earlier today, but I was not able to use the  
associations, named\_scope, etc. But you can add self.included(base)  
around all the AR associations, etc. and this will load them into your  
model class.

Here is my final setup which is working well so far:

#-----------------------------------------------------------

# /my\_rails\_app/vendor/plugins/my\_plugin/lib/base\_widget.rb

# ----------------------------------------------------------

module BaseWidget  
def self.included(base)  
base.named\_scope :expensive, :conditions=\>“price\>100”  
base.belongs\_to :manufacturer  
end

def formatted\_price  
“$”+self.price.to\_s  
end  
end

#-----------------------------------------------------------

# /my\_rails\_app/app/models/widget.rb

# ----------------------------------------------------------

class Widget \< ActiveRecord::Base  
include BaseWidget  
use\_db :prefix =\> “slave2\_”  
end

---

<div class="post-metadata">

**Author:** ![yannimac](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/y/7993a0/32.png) [@yannimac](https://www.ruby-forum.com/u/yannimac)\
**Post date:** [March 8, 2010, 9:04pm UTC](https://www.ruby-forum.com/t/extending-a-model-that-is-in-a-plugin/184208/9 "2010-03-08T21:04:26Z")

</div>

Yanni M. wrote:

> Additionally, you can include a default class in your plugin. This  
> would give you the model out of the box when you install the plugin, so  
> you don’t even have to create a model in /app/models/
> 
> #-----------------------------------------------------------
> 
> # /my\_rails\_app/vendor/plugins/my\_plugin/widget.rb
> 
> # ----------------------------------------------------------
> 
> class Widget \< ActiveRecord::Base  
> include BaseWidget  
> end
> 
> Then if you have additional functionality you need to add (like use\_db),  
> you just drop a class into /my\_rails\_app/app/models/ and it will use  
> that one instead of the default class that is contained in the plugin.

One gotcha… rails gets confused in certain situations and will throw a  
Dup error. You need to add “unloadable” to the top of the model class.

class Widget \< ActiveRecord::Base  
unloadable  
include BaseWidget  
end
