Passing param using link_to and UJS - ruby-on-rails

I'm having a hard time understanding the proper way to pass a param using link_to and UJS.
I have the following resources:
Photos
Comments
Users
A user is trying to comment on a photo by clicking "Add Comment." When this happens a box pops up using UJS showing a form rendered by utilizing a new.js.erb file. After "Create Comment" is posted the create.js.erb file is called to handle the update, which just hides the comment box and adds the comment to a list of comments.
In my index.html.erb for my photos I am doing the following:
I specify a link to add comments passing in the id of the current photo.
<%= link_to 'Add Comment', new_comment_path( photo_id: photo.id ), remote: true %>
This gives me the url: 0.0.0.0:3000/comments/new?photo_id=1, which is what I expect.
Now my question is, how do I handle this passed parameter in my new action such that I can specify something like
#comment.photo_id = photo_id
or
#comment.photo_id = params[:photo_id]
in my comments_controller.rb?
Is there something I can do in JS that will help me save the photo_id value to my #comment.photo_id column for the comment added?

First of all I'll suggest you to start using nested routes for things like comments or likes. You will find the railscast here nested_routes_railscast
Coming back to your question, use #comment.photo_id = params[:photo_id] in your controller.
There is a better approach to accomplish this, You can have the popup already on the photo show page. In the popup you can have a form for new comment model. After clicking on the specific photo you just have get the id of that photo using javascript and copy it into the hidden field for :photo_id in the form.

Yes, you can get photo_id in params, they way you have specified.
Suppose Photo has many comments in your case.
So in your case when in you get params[:photo_id] in comments_controller
you can do:-
#photo = Photo.find_by_id(params[:photo_id])
#photo.comments.create(params[:comment])
Please read about nested resources from guides.rubyonrails.org, so you can generate create comments route in restful manner.

Related

rails extra action when clicking on link

I have a rails app with notifications. Notification has :checked_at datetime attribute. On the notification index page I link every notification to the notifiable object like <%= link_to posts_path(anchor: "post_#{notification.notifiable_id}") do %>.
What I wanna achieve is when clicking on this link (that takes to the notifiable object) the notification.checked_at attribute would get updated.
I have some different solutions in my mind like an extra AJAX call when clicking on the link OR having an extra route like notifications#check_notification the link helper would point to and after checking the attribute it would redirect_to the original posts#index page.
I'm not sure which one is the preferred way (maybe a 3rd one) in rails. Could sby tell me what to do?
You could add another parameter to the route, something like update_checked_at, then on your index action inside the controller, you check if it exists and it is true.
<%= link_to posts_path(
anchor: "post_#{notification.notifiable_id}",
update_checked_at: true) do %>
def index
if params[:update_checked_at]
# Do your thing

Render polymorphic form in partial

I want to render a form for a comment in a partial called _feed_item.html.erb. This partial is used to display both Products and Requests, both of which have comments. The rendered comments form needs to be specific to which feed_item is being displayed (Product or Request).
I've created a gist to show what i've got so far. Please do let me know if anything is missing.
https://gist.github.com/aclel/82c332d9fd1a193694ef
Currently i'm able to create a link which takes me to the appropriate url to create a comment. This works well.
<%= link_to "Make Comment", new_polymorphic_path([#commentable, Comment.new]) %>
Instead of having to go to a different url, I would like to be able to render a form in the feed_item partial.

how to add a `preview` action to resources?

I am looking for the right approach to include a preview action between new and create actions.
Let's assume I have the following:
resources :users
By default, when the form is submitted:
if new, call create action;
if edit, call update action.
In this way, I can use the same form (partial) for new and create, which is great!
How can I configure the resources to include a preview between actions. I mean, forcing new to call preview and then preview to call create.
I could add a new route/action and point the form for that action, however the same form cannot be used for new and edit.
There is a way to configure the resources to do that?
Have a look at this railscast: multibutton form, it shows a form with both a 'preview' and 'submit' button, maybe that's something you might want to do.
By the way, couldn't you use the same form by passing locals to the partial? For example:
<%= form_for #profile, url: dynamic_path do |f| %>
...
<% end %>
<%= render 'form', dynamic_path: profile_preview_path %>
you have several ways to do this:
you change the url of the form to your preview action (for which you have to add a route).
you use your create action for preview and create:
i.e. you add a parameter (like ':go_to_preview') to the form submit request. if you find it in the controller you render preview.
when the user wants to confirm the preview, you submit the data again (without that parameter) and this time create the record.
there are also 2 more dynamic possibilities:
you create the preview in real-time - if that is possible (like here on SO) - and use just the create action,
a variation of the first option: when the user submits the form, you send an ajax post request to a preview action, render a partial and include it on the page, then while your user still has the form he just filled, the user decides if she wants to modify or submit definitely.
I would suggest adding a DateTime column "finished_at", "published_on", etc... whatever is appropriate for your domain.
Using blog posts as an example:
scope :published, where("published_on IS NOT NULL")
scope :draft, where(:published_on => nil)
Use the scopes and new field where appropriate to limit the follow up actions.
This approach gives you more than you asked for :
a way to limit processing based on "state"
Data on creation times versus publishing times

Help refactoring this controller logic, should this be a helper?

So if I am listing blog post entries, and under each entry I display 5 comments. There is a label below the last comment that says:
'show more'
or
'add comment'
The logic for this currently is in my controller:
#posts.each do |p|
if p.comment_count > 3
p.some_label = 'show more'
else
p.some_label = 'add comment'
end
end
I had to add a 'some_label' attribute to my posts model just for this purpose.
Does this seem right or should it be re-factored?
This feels like view logic to me and it seems a little funny to have it use an attribute on the model for something like which link to display to the user.
I would suggest going more towards the route you mentioned by making use of a helper method. When you get to the point of rendering the link below the post, just make a call to the helper which can do a quick check on the comments count for that post and could simply return the string (or full link) you are looking for in that situation.
Aside from determining how many comments the post has, this logic shouldn't need to interact directly with the model at all.

Ruby on Rails: form and radio button question

I have a form around a list of items. I would like to check a radio button on the list and then, after clicking 'Submit', go to the 'Edit' page of the selected item.
The problem is that if I am writing something like
<%= form_tag edit_item_path %>
but Rails complains that I didn't provided a proper id, which in turn is being set on my radio buttons as the following:
<%= radio_button 'item', 'id', item.id %>
So - how would I send a form with a selected id to a given action?
Doing it the way you describe would not work, since edit_item_path by default RESTful path definitions is a GET request. You are trying to make it a POST request. If you would like to stick to the RESTful way of doing things I would recommend simply looping through your items and provide links to edit, since you are planning to edit them one at a time anyways. Otherwise, you would have to define a new route if you would prefer doing things within the form with radio buttons. If you are, than you would add something like this to your config/routes.rb: (assuming you are using rails 2.3.x)
map.resources :items, :member =>{:edit_radio_form => :post}
Than your form would look like this:
<%= form_tag edit_radio_form_item_path do |form| %>
And it should work, but it not the right way of doing things for several reasons, the most anoying one of which is that you won't get a full URL on your edit page because you got there with a POST request, so if you refresh the page, your item id param will be gone and will produce an error.

Resources