How to save multiple (paperclip ) images into a rails model attribute? - ruby-on-rails

I am trying to use a WYSIWYG editor like Froala to upload images to my server. The issue is I need to store multiple images into one attribute of the model. This is because I wont know ahead of time how many images will to be stored when my users upload images.
Would be great if anybody can give me some pointers. Or examples.

Have a look at http://guides.rubyonrails.org/association_basics.html and search for has_many. You need an extra model which stores the images and which has an other_model_id attribute which points to the other model.
If you have never worked with has_many you'll find an example application at http://www.xyzpub.com/en/ruby-on-rails/4.0/activerecord_has_many.html

If you have to save several images related to a model, you'll need an 1 - N relation.
So you have two choices:
Create a model like album and make an 1 - 1 relationship
Use an has_many (1-N) relationship.
To learn more about associations I really recommend you to read the official guide.

class User < ActiveRecord::Base
has_many :images
accepts_nested_attributes_for :images
end
class Image < ActiveRecord::Base
belongs_to :user
#use paper clip for the following method
has_attached_file :attachment
end
Now upload the images using your WYSIWYG editor, and append nested images form to the user form, submit the form and you are good to go. Hope this helps.

Related

How Do I get the class to which the current class belongs to?

I have an uploader (carrierewave) to save several files, but I'm afraid that some days, some files will have the same name and will cause a problem. Moreover, I'd want the folders to keep a semblance of organization.
So, I have a first scaffold, "magazine" that allows me to create a magazine with its title and several images. The second scaffold that I use, "page", allows the multi upload system.
With this method, my models look like this:
magazine.rb
has_many :pages, :inverse_of => :magazine, :dependent => :destroy
pages.rb
belongs_to :magazine
Now in my uploader, I have the following:
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}"
end
which creates folders like this : "uploads / page / image", then uploads every single images inside it, even thought if it's for an other magazine, so the images get mixed up.
My question is the following: is there a way to get to write the magazine's ID instead ? This implies to find the class "pages" belongs to, but I didn't find anything answering my question on google.
Thank you in advance
If you have a custom uploader mounted in the model Page you could access the model attributes normally
PageImageUploader.rb
def store_dir
"uploads/magazines/#{model.magazine.id}/#{model.id}"
end
However, you can't access the models IDs unless your models are persisted. A workaround for that can be find here.

Rails forms for adding / removing associations

I would like to know how to add / remove associations in a form. Lets say I have two models linked by foreign keys
class Event < ActiveRecord::Base
has_and_belongs_to_many :participants
end
class Participant < ActiveRecord::Base
has_and_belongs_to_many :events
end
I have created some forms to edit each model. However, is there a way to use the form to remove/add a participant from/to a lecture? (I guess this would require some javascript to add / remove entries in the view as well as well...)
What you are looking for is accepts_nested_attributes_for and some js magic. Ryan Bates describes this perfectly in some of his free episodes:
Nested Model Form Part 1
Nested Model Form Part 2
And here is the full source code of this episodes.
Maybe you'll have to adapt some things because it's a little old, for instance replace link_to_function for a simple link_to with an :onclick event, but I think pretty much everything else works on Rails 4.
Hope it helps!

Limit number of images - Paperclip

I have User model with the following association:
class User < ActiveRecord
has_many :pictures, :as => :imageable
accepts_nested_attributes :pictures
end
My Picture model looks like this:
class Picture < ActiveRecord
belongs_to :imageable, :polymorphic => true
has_attached_file :image
end
Now, I want to user to be able to upload maximum 5 images. And he will select 1 image as his avatar. Now, user can upload images but I don't know how to limit the maximum number of pictures. One more thing, user needs to be able to change his avatar image. How can I achieve this?
In my view, I use input file with name user[picture_attributes][0][image] in order to allow user to change the first picture but it keeps inserting new pictures into database instead of replacing the first picture.
Please help me on this.
Thanks in advance
For the first part of the problem you have, i would suggest you use rails built-in counter_cache method.
Your picture model would thus become:
class Picture < ActiveRecord::Base
belongs_to :imageable, :polymorphic => true, counter_cache: true
has_attached_file :image
end
Also you would need to add a column called pictures_count to the User model.
This way in your controller you could check if the count is upto 5 records and therefore inform them that they have uploaded the maximum allowed.
if #user.pictures.size == 5 #sorry no more uploads
For the second part of the problem. Is the form action pointed to the new/create action or to your update action. If pointed to the new action a new record would be created but if pointed to the update action then it should change the first image record as you expect.
#charinten For the second part of the problem, some suggestions:
You could try making the id of the pictures accessible in the user model. This way when you try to point to the image to use as an avatar, rails uses that id to update the record. If you try to update the record without pointing rails to that id, it would assume you are trying to create a new record.
Also rather than using user[picture_attributes][0][image] you could in your user profile. Find a specific image and point to that image on the edit action.
Hope this helps

How do you create a has_many association with multiple types?

I have the following:
a Link model
a LinkItem model, which I want to be of the following type
a comment
a tag
...
I am using this code:
Link model
class Link < ActiveRecord::Base
has_many :link_items
end
LinkItem model
class LinkItem < ActiveRecord::Base
belongs_to :link
end
class Comment < LinkItem
end
class Tag < LinkItem
end
Now I don't know how to tell Rails that my LinkItem model is supposed to be polymorphic. I've read the Rails Guide on asociations and other tutorials, but these just describe how to create a belongs_to association to multiple other models, not the other way around.
So my question would be:
How do I create a has_many association where the associated instances can be of different types? Or would it be better to create seperate models for comments, tags, etc. and just associate each of them individually with my Link model?
EDIT
Actually my code works.
I just tried using a 'type'-column (instead of 'link_item_type') in my database and rails automatically used it to save/determine the correct subclass of my LinkItems (thanks Wizard of Ogz for the hint)
However I still can't access the subclasses of LinkItem without referencing a LinkItem first. Is this some kind of lazyloading?
If you are looking for polymorphic association nicholaides has the right way .
If you are looking for has_meny polymorphic association , check out the answer to "Setting up a polymorphic has_many :through relationship".
This is called a polymorphic association. Here is some documentation.
I just dealt with what I think is the same issue.
My filename for my model was wrong. I initially created it with one name (ex. link_tag.rb), and then changed the name of the class (ex. from LinkTag to Tag) on the fly without changing the name of the file (ex. tag.rb).
When I renamed the file correctly, it worked as expected.
In summary, the name of the file needed to match the name of the class.
I know this post is a little old, but maybe that will help someone someday!
I user polymorphic associations a lot!
I would first watch this RailsCast and then the documentation suggested by nicholaides.
It perfectly explains how to create both sides of the association.

How to access and submit related polymorphic models in the same form, in Rails?

Suppose I have 3 models, Car, Motorcycle and Truck, and for each I have to enter a bunch of stuff, such as a list of known previous owners, traffic tickets, license plates, etc. So I created a model for each (PreviousOwners, PreviousPlates, etc) and set up polymorphic associations for the related models.
The problem is, how can I enter all of that using just one form, kind of like this:
Car #123
Known previous owners:
Jason Jazz
Brian Bass [add another]
Known previous license plates:
12345
67890 [add another]
Current status:
Cleared
(this is a dropdown select menu, CurrentStatus is also a polymorphic association, but with predefined values.)
etc
This is proving to be a bitch, way beyond my level of expertise (newbie here). The resources are not nested and almost everything I find on multiple models is for nested resources, and nothing seems to apply to polymorphic associations.
(This is just an example, I know ideally I should have a Vehicle model with 'Car', etc, as categories, but it's just to illustrate the real need for polymorphic models in my case.)
Thanks.
Maybe the PresenterPattern is helpfull too:
http://blog.jayfields.com/2007/03/rails-presenter-pattern.html
The basic idea is to create a presenter which acts like a model and processes all the incoming data from your form and distributes it to the models. This way it's also easy to create multiple instances of lets say PreviousOwner and attach it to Car.
Check the link out!
You can use the new nested attributes in Rails 2.3, but there is a certain way you have to write it to make it work. The trick is that you need to create the actual polymorphic object, then build the class that has the belongs to polymorphic clause in it. This is an example I found at Ryans Scraps, posted by a user named: Superslau (I've cleaned it up a good bit for here):
This feature is really awesome. I have
implemented this with polymorphic
associations, and it works!
class Task < ActiveRecord::Base
has_many :assets, :dependent=>:destroy
accepts_nested_attributes_for :assets, :allow_destroy => true
belongs_to :workable, :polymorphic => true
end
class Upload < ActiveRecord::Base
has_one :task, :as => :workable, :dependent=>:destroy
accepts_nested_attributes_for :task, :allow_destroy => true
end
Upload is a kind of task. All tasks
can have one or more assets uploaded.
I took me a while to figure out that I
should use the Upload model as the
parent. So in one form, I can create
an upload, and it’s corresponding task
entry, along with a file upload.
in my controller:
def new
#upload = Upload.new
#upload.task = Task.new
#upload.task.assets.build
end
Don’t
worry if that doesn’t make any sense,
I just wanted to let people know that
accepts_nested_attributes_for works
just fine with polymorphic
associations. Thanks Eloy!
Very well, nested form builders doesn't have to be associated with nested resources AFAIK.Can you post your models code as well?
There is a RailsCast on Complex Forms that might help you with building a single form from multiple models.
If the car/motorcycle/truck models are identical, you should add a type column to your vehicle model. If they're not, you should use STI (single table inheritance).
But yeah, need to see your models first before I can give you code.
You can avoid this and make things a bit simpler by introducing a Vehicle model. The Vehicle model can have all your PreviousOwners, PreviousPlates, etc collections, and then your Truck, Car and Motorcycle models can has_one Vehicle.

Resources