How to setup delete selected messages feature in ruby on rails - ruby-on-rails

I'm about to finish the final part of my thread messaging system for users. All deletion works great however before I move on to my next feature I'd like to give users the ability to delete selected messages.
Here's a way I've thought of doing it so far.
Add a check box tag to the each loop that loops through each message.
Have a "delete selected" link that goes to my messages controller "destroy_selected_messages" action.
What I need to do is some how grab an array of all the selected messages id's. Then pass it to the path as an argument. The delete all links path.
<%= link_to 'Delete Selected', messages_destroy_selected_messages_path(ARRAY_WITH_IDS), :method => :delete, :confirm => "Are you sure?" if #current_thread_messages.any? %>
This delete selected link won't be part of the loop because I don't want it showing for every message but at the top of the thread instead.
I need to figure out how to pass the array with all the selected messages ideas into that argument. How do I get them from the each loop without going into my messages helper and writing some funky method.?
I have the checkbox tag e.g. check_box_tag ... how do I setup an empty array and then so I can pass in the messages id? e.g.:
<%= check_box_tag ......., :value => message.id &>
Help would be appreciated. I looked at an old screencast in railscasts but it's from 2007 I think.
Kind regards

You can make name="message_ids[]" for multi select inputs. It will get passed as an array through HTTP server to your params[:message_ids].
From the HTML side of the problem, I think that form helper <%= check_box_tag "message_ids[]", :value => message.id %> should suffice.
In the controller action, log the params[:message_ids] and look it up, it should be an Array.

Related

rails: link_to to pass list of selected checkboxes into params

I am not sure what the correct approach is for my situation:
I want to create a link_to pushing all checkboxes with value="1" into an array, or individually if array is not possible, but I am at a loss of how to express that?
<% #cards.each do |card| %>
<%= check_box("#{card.name}", card.id, {checked: true}) %><%= "#{card.name}" %>
<% end %>
(Rails 4.2)
After a long time of dead ends, trying to make it a 'clean' solution I ended up with this very dirty approach. But as they say, done is better than perfect:
Create a link_to that would include all the cards, but add one additional params: user_selected_cards = "".
Create a javascript that listens to for checking/unchecking of the checkboxes and reads the id associated with that specific checkbox. Then take that incoming info and add or remove it to the actual url that the link_to generates by finding the user_seletected_cards= portion in the url and add or remove the id depending on if isn't or already is added to the list after the equal sign.

Rails 4 update inside for loop

I have a view show.html.eb that displays details for an Order and displays all available Delivery Slots for the date of the order.
Eg:
Order 1
12/12/14
Delivery slots:
6.30 - 7.00
7.30 - 8.00
8.00 - 8.30
I then have a link next to each delivery slot which when clicked updates the field delivery_slot on the Order to the Id of the delivery slot that was clicked.
View Code
<% #slots = DeliverySlot.all.select {|slot| slot.day == #order.date} %>
<% #slots.each do |slot| %>
<%=slot.start_time.strftime("%I:%M%p") %> - <%=slot.end_time.strftime("%I:%M%p") %>
<%= link_to "Order", Order.update(#order,:delivery_slot => slot) %>
<br>
<% end %>
The issue is, when you click one Order link, all the order links are clicked (I can see this through the SQL in the terminal) so the end result is the delivery_slot field is always populated with the last delivery slot of the loop.
I appreciate that I am missing something here so could anyone explain:
1) Why all Order links are "clicked" when only 1 is clicked in practice.
2) Is there a better way to update the delivery_slot attribute on the Order?
Thanks
You are issuing an update when rendering the view.
<%= link_to "Order", Order.update(#order,:delivery_slot => slot) %>
You need to provide a path (or url_options which can be used to generate a path) as the second argument to link_to. Instead you are calling the update method. So when your view is rendered, you iterate over every delivery slot and issue an update for each one of them and as you have noted, the last one overwrites everything else.
If you observe your logs you will see that the SQL statements are seen in logs lines corresponding to the show request. You are updating the order even before any link is clicked.
Now since the link_to does not get a valid path, the actual HTML link is not pointing to anything. Clicking on it would be a no-op.
ri link_to is what you need to read.
So I finally arrived at the answer:
<%= link_to "Order", order_path(order:{:delivery_slot_id => slot}), :method => :put %>
I think what tripped me up in the end was that my strong parameters specific :delivery_slot_id and I was specifying :delivery_slot so I assumed I was doing something wrong when the answer was very simple.

How do I create a button that increments an attribute of a model and can be pressed once per browser?

An apartment_listing has many reviews, and a review belongs to an apartment_listing.
In the file views/apartment_listings/show.html.erb, I show a list of reviews for that particular apartment_listing. These reviews are generated with the partial view apartment_listings/_review.html.erb like so:
<%= render :partial => "review", :collection => #apartment_listing.reviews %>
In _review, I want to have a button that, when pressed:
Increments that review's helpful_count attribute.
Makes it so that it cannot be pressed again while in the same browser - probably using cookies.
I feel like the former shouldn't be too hard to figure out, but it's got me beat. I'm really not sure where to start with the second goal.
EDIT: I managed to update the review's helpful_count attribute with this code in apartment_listings/_review.html.erb:
<%= form_for review, :method => :put, :remote => true do |f| %>
<%= f.hidden_field :helpful_count, value: (review.helpful_count + 1) % >
<%= f.submit 'Helpful?' %>
<% end %>
However, I'm not sure if this is the best way to do it, and I'd like to be able to disable the button after it is clicked.
Your code for updating helpful_count has the potential for problems. Imagine two users have loaded an apartment on their web page. One of them marks it helpful, and the next one does as well. Since when they initially loaded the page, helpful_count was the same, after both of them click helpful, the count will only be incremented by one: it would be updated twice to the same value.
Really, you want to create a new action, probably under the reviews resource for an apartment. That action could use ActiveRecord's increment method to update the helpful_count (technically there's still a race condition in increment!, you'd encounter it much less often) http://apidock.com/rails/ActiveRecord/Persistence/increment%21
Cookies seem like a reasonable solution for the latter problem. Simply bind to submit on the form with jQuery, and create the cookie in the handler.
What does the code look like in your reviews controller? More experienced RESTful coders might be able to speak more coherently on this, but the way I see it, incrementing the helpful_count attribute should be an action sent to the reviews controller. That way, you can create a link that performs the action asynchronously.
For example, inside _review.html.erb:
<% collection.each do |review| %>
<%= link_to "Mark as Helpful", "/apartment_listing/#{#apartment_listing.id}/reviews/#{#review.id}/incHelpful?nonce=#{SecureRandom.rand(16)}", :remote => true, :method => :put %>
# ... Do something cool with your review content ...
<% end %>
Inside your ReviewsController class:
def incHelpful
unless params[:nonce] == session[:nonce][params[:id]]
#review = Review.find(params[:id])
#review.helpful_count += 1
#review.update_attributes(:helpful_count)
session[:nonce][params[:id]] = params[:nonce]
end
render :nothing
# Optionally return some javascript or JSON back to the browser on success/error
end
Inside /config/routes.rb:
put "apartment_listing/:apart_id/reviews/:id/incHelpful" => "reviews#incHelpful"
The main idea here is that actions that edit a resource should use the PUT http method, and that change should be handled by that resource's controller. Rails' built-in AJAX functions are engaged by setting :remote => true inside the link_to helper. The second concept is that of a nonce, a random value that is only valid once. Once this value is set in the user's session, subsequent requests to incHelpful will do nothing.

Ruby on Rails - Passing values to a link_to

I'm a RoR beginner and am using Rails 3.2.3.
I have a search form on my page and it performs a get request and filters the results correctly.
I want to add the possibility of also searching Products by dates.
I inserted a date_select and am able select the date and when the page refreshes after the search, the chosen dates are still there on the date_select, as I am able to get them through params.
However, my issue is that when the page renders the products, they have a link_to to their show action.
My goal is to also pass alongside the url the dates that were selected to perform the search on that link_to.
For ex, if the user selects a date of 20-06-2012 to 25-06-2012 it only shows products inserted on that time frame (and all those params are on the url)
But the link to show action of each displayed product is only:
link_to <%= link_to product.name, product%>
which renders
http://localhost:3000/products/24 (por example)
what I want to render/show is something like:
http://localhost:3000/products/24?from=20-06-2012&to=25-06-2012
The selected dates to perform the search are not stored in the database at this moment, but I will need to get them from the URL on a latter page, therefore, both dates will need to be preserved through 2 different pages before the users fills a form and then those dates are inserted in the DB.
Any tips on this? I've searched but all I found was on how to pass variables that exist in the model and I do not want to use cookies nor session variables.
Thanks in advance,
Regards
If you want to pass arbitrary parameters to the following call
<%= link_to product.name, product %>
you need to invoke the path method explicitly instead of using the implicit version. The line above is equivalent to
<%= link_to product.name, product_path(product) %>
Then you can pass parameters
<%= link_to product.name, product_path(product, :from => 'whatever', :to => 'whatever') %>
Can you try like this
link_to <%= link_to product.name, product, :param_you_want => "value you want" %>
Now you can set value in "param_you_want" as you wish.
But in my case set value in it "value you want"
Hope you can get idea

How to show the content of the form just entered in the ":confirm =>" option on Ruby on Rails

I am trying to have a way of confirming the information entered before actually saving it to the DB
Considered making an individual confirmation page as discussed here
Ruby on Rails: Confirmation Page for ActiveRecord Object Creation
However my form includes an attached file using paperclip which makes it more of a hassle to implement.
I thought of just having a :confirm => pop up that would show the information that the user
had just entered.
The problem is how to show the information that the user had just entered, for example
<% form_for #entry, :html => { :multipart => true } do |f| %>
<%= f.error_messages %>
<%= f.label :name %><br />
<%= f.text_field :name %>
<%= f.label :file %><br />
<%= f.file_field :file %>
<%= f.submit 'Create', :confirm => "????? " %>
<% end %>
Given that your loading attachments it may not be a bad idea to render a staging view including information derived from the attachment allowing the user to confirm. As in display the file if it's an image, or the first paragraph of text if it's a text file, etc.
It's going to take more work than the just adding a confirm pop up, but I feel the enhanced user experience is worth the extra effort.
I'm not familiar with the way that paperclip works. So you're mostly on your own for the intimate details.
You will probably have to create a record before the staging view can be rendered with the sample of the uploaded file. To accomplish that I'd set up an "active" column on the model in question, that defaults to false.
Usage would look something like this:
User complets new form.
Attachment is updated and records are saved, with the active field set to false.
Redirected to confirmation page that is essentially the show page with a confirm link/button and a cancel link/button
a. When the confirm link/button is clicked it sends a request to the controller triggering the update action on this record setting active to true.
b. When the cancel link/button is clicked it sends a request to the controller trigering the destroy action on this record.
All that's left is to set up a recurring task to remove objects that are inactive and were crated long enough ago that it's safe to assume the user has just ended the browser session.
The confirm option for the Rails submit method can only take a text value.
If you want to dynamically generate the confirm text, one way you could do it is to write your own HTML submit tag, and write custom javascript to analyse the fields you want to use in your generated text.
Or you could use the Rails submit method, but use something like JQuery to add an event handler to it.
I'd just throw my js into an onclick handler. That's all Rails does.
<%= f.submit 'Create', :onclick => "confirm('Name is ' + $F('entry_name'));" %>
(note, didn't test that, but it looks close. confirm is a core js function, not part of any lib)

Resources