Paperclip with albums - ruby-on-rails

I'm struggling with paperclip and adding the attached images to albums. Should I be writing an album_id to the images row in the database? Right now, I'm trying to use an album model, which belongs_to :user and has_many :photos. The photo model belongs_to :album and has_attached_file. Is that the way to go about it?
I'm really new to Rails so i'm still getting hung up on things like...
<%= form_for #album, :html => { :mulitpart => true } do |f| %>
because I have no idea how #album is suppose to point to the right controller/action. Another thing is how the h*ll is photo suppose to know which album its apart of? Normally I would have said save the album_id in the photo row but I feel like I'm passing up paperclips functionality.
Rails still hasn't "clicked" for me =/
I think PHP ruined me...or the auto-magickness is too powerful for my mind.

There is no Magic in Rails . It all about how you understand the concepts . In order to understand the rails following things are essential
Basic Knowledge on Ruby
Agile web development will be kick start (Understand MVC Architecture)
Debugging Rails application and script/console
Coming back to your above Paperclip application .
Here #album is an instance variable which holds the value of the form fields like the title ,image etc.
<% form_for(#album,:url => {:controller => "albums" , :action => "create" }) do |f| %> correct syntax is this , which points to the albums controller create action , if you are familiar with the routes you can use new_album_path will also routes as same as above.
h*ll is photo suppose to know which album its apart of? Answer is through specifying Associations in the Model between album and Photo and User. Based on your requirement. set the associations. Associations are the relationship between to two tables , Like in PHP you do foreign key and relate two tables . Best book to learn this is Pro Active Record
Here is a nice tutorial by Jimneath
Hope it helps !

Related

Multiple image upload Rails

I have been stuck on a problem for three weeks now, and although I have tried everyday to find an answer to my problem, I haven't found anything that I have been able to make work. If anyone could help me, I would be very, very grateful.
I have built a basic blog in Rails that allows an admin user to publish articles using a form, containing a title text_field, body text_area, and file_field for an image, which uses Paperclip. All very simple and easy and no problems there. However, I have been trying to alter the form to allow an admin user to upload multiple images as part of a new article, but have been unable to find a way to do this.
I need a solution that will allow me to achieve multiple image upload functionality in a form. I have tried many gems and many tutorials, but have been unable to integrate anything into my app without completely breaking it. Can any one help me get out of this dead end I've found myself in for the last three weeks? Do you have any clear tutorials or solutions that will help me overcome this problem?
Thank you very much to anyone that can help me.
Your question is quite broad, without any schema or anything so I'll try to help you as much as possible given that.
If it's a blog, you might have a post model.
You could have a photo model, with a reference to the post model. If you add paperclip to your photo model, then you can save multiple photos.
There are multiple ways to do this. The first one I think of is using nested forms with a gem like cocoon.
The second I think of is using a dropzone, which would upload the photos using Ajax.
By default PaperClip allows you to upload one attachment. However, a clean way I've found to work around this is to create another model which would wrap around the images.
class Article < AR::Base
has_many :images
accepts_nested_attributes_for :images
end
class Image < AR::Base
belongs_to :article
has_attached_file :filename, styles: { medium: "300x300>", thumb: "100x100>" }, default_url: "/images/:style/missing.png"
validates_attachment_content_type :filename, content_type: /\Aimage\/.*\Z/
end
Don't forget to run a migration to create the images table:
rails generate model image article:references
and
rails generate paperclip image filename
Then in your articles/form, where you initially had the field to upload the image, you would have
<%= f.fields_for :images do |p| %>
<%= p.label :filename %><br>
<%= p.file_field :filename%>
<% end %>
In your articles_controller#article_params, along with the current params, you would have, params.require(:article).permit(..., images_attributes: [:filename])
Afterwards, allowing the uploads of multiple images would therefore only require the basic knowledge of nested forms.
To set a default number of file_fields, in your ArticlesController#new after initializing your #article you would have
def new
#article = Article.new
2.times{ #article.images.build}
end
With this setup, when you navigate to your new_articles route, you should see your article ready to upload 2 images.
To learn more about how to use NestedForms to do even more, you should see Ryan Bates tutorial.
This approach provides a cleaner interface, as the other approaches, I guess, would require some sort of hack.
Let me know if I'm able to help or further clarifications required.

How to define a link path

I'm trying to figure out how to make an app with Rails 4. I keep getting stuck on basic things and I don't seem to be able to identify principles to use going forward.
I have a profile model and a industry model. The associations are:
Profile:
has_and_belongs_to_many :industries, join_table: 'industries_profiles'
Industry:
has_and_belongs_to_many :profiles, join_table: 'industries_profiles'
In my profile show page, I'm now trying to link to the industry page:
<% #profile.industries.limit(5).each do |industry| %>
<%= link_to industry.sector.upcase, industry_path(#industry) %>
<% end %>
I can't find anything that works for this link.
I have tried the following:
industry_path(#profile.industry)
industry_path(#profile.industry_id)
industry_path(industry)
industry_path(profile.industry)
industry_path(industry.id)
industry_path(industry_id)
But all of them are guesses. I don't know how to ready the API dock so I can't understand any of its content.
Can anyone see how to link to a show page of the other side of the HABTM association for a single record?
You can grab a list of your routes by running rake routes | grep industry in your command line, which will give you a table with the prefix, action, and uri pattern. For example:
industries GET /industries(.:format) industries#index
POST /industries(.:format) industries#create
new_industry GET /industries/new(.:format) industries#new
edit_industry GET /industries/:id/edit(.:format) industries#edit
industry GET /industries/:id(.:format) industries#show
PATCH /industries/:id(.:format) industries#update
PUT /industries/:id(.:format) industries#update
DELETE /industries/:id(.:format) industries#destroy
In your case, you should look at the show path. Which is industry and you append _path to the end of whatever your prefix is above, which comes out to be industry_path. And since you have declared your variable industry when defining your loop, you can use that instead of the instance variable.
Short answer: industry_path(industry)

Nested Ressources in Ruby on Rails

It's actually supposed to be very trivial, but I'm experiencing strange issues.
I'm developing a Game Database, where Users can chart Game Entries and also write reviews to those reviews. Of course a Reviews URL (the show view) must be dependent of the game's id, like localhost:3000/games/1/reviews/2
So these are my routes
resources :games do
resources :reviews
end
And I want to open the show-view of a review with
<%= link_to "zum Review", game_review_path(#game, #review) %>
this is all basic tutorial stuff.
But I only recieve a Routing error. Trying instead this approach
url_for([#game, #review])
At least won't result in a routing error, but Not the reviews show-view is opened, but the game's show view, which is where this link is actually placed!
My models associations are set corretly and my controllers actions are all basic tutorial stuff. What am I doing wrong?
In your erb file try passing the local variable in the left argument and the name of the nested model in the field to the right. If you use 2 local variables you will get a routing error. #game is the local variable and review is nested under games so the below code should fix your issue.
Try:
<%= link_to "zum Review", game_review_path(#game, review) %>

How to handle avatar upload in REST manner

I have User model, where user should be able to upload one picture as an avatar. But I don't really know how to implement this in correct REST way. I see two options
First I think of avatar as of member resource that belongs to user, so I add two actions to my Users Controller, one avatar for the upload form, and second action for handling the actual upload avatar_upadte, so my routes look like
map.resources :users, :member => { :avatar => :get, :avatar_update => :post }
Second I can think of avatar as of separate resource and create Avatars Controller instead, which would be like
map.resources :users
map.resources :avatars, :only => [ :new, :create ]
I don't want to handle avatar upload in edit_user action, since it is already pretty complex.
The third option could be to have only avatar action to display the form and then user REST user update action as upload target, where form would be something like this
<% form_for #user, :url => user_path(#user), :html => { :multipart => true } do |f| %>
<%= f.label :avatar, 'Avatar' %>
<%= f.file_field :avatar %>
<%= f.submit 'Upload' %>
<% end %>
But I don't like this this attitude either, because since my update action already handles another form, it would be pretty ugly to handle redirects etc.
For the app I work on we do something like this:
map.resources :users do |u|
u.resources :avatars # You can also make this a singleton resource
end
This gives you a route like: /users/1/avatars/new
This might not make sense for your app, if not I would choose the option of having a separate AvatarsController.
If I understand correctly:
Option 1 adds a custom action to the User resource, which is best avoided if at all possible.
Option 2 splits User and Avatar into separate resources, but doesn't make it easy to connect the two (for example, when creating an upload form).
Option 3 looks like you'd view the Avatar as a User attribute.
The most important thing to figure out at this point is: what's the cardinality of the relationship between User and Avatar. Does a User have one Avatar or many? If there's a one-to-many relationship, then a solution like the one Jonnii proposes might make sense.
If a User will only have one Avatar (which seems likely), I would consider going with the simplest solution and make the Avatar a User attribute.
Although I haven't gotten around to trying it out, I've heard good things about Paperclip. The example usages even discuss using Paperclip with avatars.
For an even more lightweight solution, you might consider Gravatar, which would eliminate the need for a file upload entirely and simplify things a lot.

Adding a photo to a model's has_many model from a view

I have a model, Thing, that has a has_many with ThingPhoto, using Paperclip to manage everything. On the "show" view for Thing, I want to have a file upload, and have it relate to the Thing model.
For some reason, I'm totally glitching on how this should be done. I've tried doing this (Haml):
- form_for #thing.thing_photos, :html => {:multipart => true} do |f|
= f.file_field :photo
= f.submit
... and I get this error:
undefined method `array_path' for #<ActionView::Base:0x24d42b4>
Google is failing me. I'm sure this is super easy, but I just can't get my brain around it.
Edit: I should have mentioned that if I change the #thing.thing_photos to just #thing, it works fine, in that it displays the form, but of course it's not associated with the correct model.
try #thing.thing_photos.new
this should instance a new model of thing_photos. If you're not using nested routes you'll have to add the thing_id as a hidden field.
If you're not tied to Paperclip (and if you're just doing images), I've had a lot of luck with fleximage. It's got really good documentation for image upload, manipulation, and display (with all sorts of neat effects like watermarking and stuff).
It doesn't quite answer your question, but it might be a cool thing to look into.
But I bet your problem related to the fact you're creating a form for an array of objects (through an association). I bet something is finding the type of the object (should be "thing_photo" but is "array" in your example), and appending "path" to it to write the form post URL. Perhaps you should add a .first or create a partial?
The form should be for #thing_photo and should either pass in the thing_id or if it's a nested route you can get it from that
then in your thing_photos controller
#thing_photo = Photo.new(params[:thing_photo])
#if using nested route
#thing = Thing.find(params[:thing_id])
#if using hidden field
#thing = Thing.find(params[:thing_photo][:thing_id])
if #thing_photo.save
#this is what ties the thing photo to the thing
#thing.thing_photos << #thing_photo
end
If I understand the question correctly, this might help.

Resources