# Models with attachments and one AttachmentsController: how?

**URL:** <https://www.ruby-forum.com/t/models-with-attachments-and-one-attachmentscontroller-how/149957>\
**Category:** Rails\
**Created:** [October 1, 2008, 4:57pm UTC](https://www.ruby-forum.com/t/models-with-attachments-and-one-attachmentscontroller-how/149957 "2008-10-01T16:57:16Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![carminem](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/90db22/32.png) [@carminem](https://www.ruby-forum.com/u/carminem)\
**Post date:** [October 1, 2008, 4:57pm UTC](https://www.ruby-forum.com/t/models-with-attachments-and-one-attachmentscontroller-how/149957/1 "2008-10-01T16:57:16Z")

</div>

First off, I beg your pardon for the somewhat cryptic topic, but I  
couln’t think of anything better.

The issue I’m facing is that I have some models (User, Product, Maker)  
which can have one or more  
attachments:

A User has\_one avatar  
A Maker has\_one logo  
A Product has\_many pictures, and has\_many documents

“Avatar”, “logo” and “documents” are all aliases for a model named  
“Attachment” and, thus, the  
aforementioned relations are all polymorphic.

I’m using “attachment\_fu” plugin to handle attachments.

While writing the code I’ve found that there are many such constructs  
repeating all over:

def update  
flash[:error] = “couldn’t update product” unless  
@product.update\_attributes(params[:product])  
if !params[:attachment].blank?  
flash[:error] = “couldn’t add the attachment” unless  
@product.attachments \<\< Attachment.create(params[:attachment])  
end  
redirect\_to edit\_product\_path(@product)  
end

This smells a lot. I thought there should be one controller in charge of  
handling attachments, namely  
AttachmentsController, so far so good.

But…since the AttachmentsController would be “REST style”, it will  
only have one “create” action which  
will be used in different contexts (User, Product, Maker).  
Create action will be passed the usual “params” hash built like this:  
:xxxxx\_id =\> 1, :uploaded\_data =\> “…”

Where “xxxxx\_id” will be replaced by “user\_id”, “product\_id” and  
“maker\_id” depending on the what  
model I’m creating attachment for.

Being params: :user\_id =\> 1, :uploaded\_data =\> “some stuff”

I thought the AttachmentsController#create action should look like:

context = params.keys.find do |k| k.to\_s =~ /._\_id/ end  
class\_type = eval(context.to\_s.gsub(/._\_id/,’’).classify)  
instance = class\_type.find(params[context])  
instance.attachments.create(params[:uploaded\_data])

Is that a correct way to proceed, or there’s an easier and cleaner way?

Thanks in advance for your help

Regards,  
Carmine

---

<div class="post-metadata">

**Author:** ![carminem](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/90db22/32.png) [@carminem](https://www.ruby-forum.com/u/carminem)\
**Post date:** [October 1, 2008, 9:02pm UTC](https://www.ruby-forum.com/t/models-with-attachments-and-one-attachmentscontroller-how/149957/2 "2008-10-01T21:02:42Z")

</div>

what you’re describing is a polymorphic association.

> **[ActiveRecord::Associations::ClassMethods](https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#M000980)**
>
> Associations are a set of macro-like class methods for tying objects together through foreign keys.

---

<div class="post-metadata">

**Author:** ![carminem](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/90db22/32.png) [@carminem](https://www.ruby-forum.com/u/carminem)\
**Post date:** [October 1, 2008, 9:33pm UTC](https://www.ruby-forum.com/t/models-with-attachments-and-one-attachmentscontroller-how/149957/3 "2008-10-01T21:33:12Z")

</div>

Hi Jeff,

Jeff Emminger wrote:

> what you’re describing is a polymorphic association.  
> [ActiveRecord::Associations::ClassMethods](http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#M000980)

Indeed, Attachment is associated polymorphically to the other models.

What I want to accomplish is removing code duplication from some of the  
controllers.  
Let’s say I have:

- User has\_one :attachment, :as =\> :attachable
- Maker has\_one :attachment, :as =\> :attachable
- Product has\_many :attachments, :as =\> :attachable

Now, in their respective controllers, the “update” action looks like  
this:

def update  
flash[:error] = “couldn’t update product” unless  
@product.update\_attributes(params[:product])  
if !params[:attachment].blank?  
flash[:error] = “couldn’t add the attachment” unless  
@product.attachments \<\< Attachment.create(params[:attachment])  
end  
redirect\_to edit\_product\_path(@product)  
end

The “interesting” part is the one where the Attachment gets created and  
associated to its “owner” (in  
that case, the Product).

This part is repeated also in the UsersController and MakersController.

I thought that, trying to comply to the “everything is a resource”  
mantra, I should move that part outside the afore mentioned controllers  
and in a controller of its own. Say: AttachmentsController.

Routes are set as follows:

map.resources :users do |user|  
user.resource :attachment, :controller =\> ‘attachments’  
end

map.resources :makers do |maker|  
maker.resource :attachment, :controller =\> ‘attachments’  
end

map.resources :products do |product|  
product.resources :attachments, :controller =\> ‘attachments’  
end

This leads to a problem.  
User, maker and products “edit” view will have to use  
AttachmentsController in order to create  
a new attachment for their respective model. Hence, they will all call  
AttachmentsController#create action passing parameters.

To solve this problem, I thought of implementing the “create” action  
that way:

context = params.keys.find do |k| k.to\_s =~ /._\_id/ end  
class\_type = eval(context.to\_s.gsub(/._\_id/,‘’).classify)  
instance = class\_type.find(params[context])  
instance.attachments.create(params[:uploaded\_data])

And the question is:  
is it correct to have AttachmentsController handle the attachments of  
user, maker and product models, or should I stick with the shown  
“update” action and let UsersController, MakersController and  
ProductsController handle the attachments?

Now, I beg your pardon if I’ve been unclear (my english is worse than my  
code 🙂 ).

Thanks for your help

---

<div class="post-metadata">

**Author:** ![carminem](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/90db22/32.png) [@carminem](https://www.ruby-forum.com/u/carminem)\
**Post date:** [October 27, 2008, 10:16pm UTC](https://www.ruby-forum.com/t/models-with-attachments-and-one-attachmentscontroller-how/149957/4 "2008-10-27T22:16:53Z")

</div>

> And the question is:  
> is it correct to have AttachmentsController handle the attachments of  
> user, maker and product models, or should I stick with the shown  
> “update” action and let UsersController, MakersController and  
> ProductsController handle the attachments?

It’s correct in my opinion… you have only one place to maintain the  
attachment code.
