ActiveScaffold url_options - ruby-on-rails

I am very new to Ruby and Rails and I am trying to make a modification to a page that is generating the Show, Edit and Delete links for the records using activescaffold. The issue I have is that the page that I am looking at has the links being generated automatically by activescaffold and I need to change only the Delete link to go to another page where I can display a message that will say, You are deleting "option blah blah", Are you sure you want to do that? and give them a cancel and ok button.
My issue at this time is I am not sure where to look for where the links are being generated and hence I am not able to target the new page.
Here is the code that is creating the links
<table cellpadding="0" cellspacing="0">
<tr>
<td class="indicator-container">
<%= loading_indicator_tag(:action => :record, :id => record.id) %>
</td>
<% active_scaffold_config.action_links.each :record do |link| -%>
<% next if controller.respond_to? link.security_method and !controller.send(link.security_method) -%>
<td>
<% if record.class.statused? and record.disabled? -%>
<%= link.action.to_sym == :enable ? render_action_link(link, url_options) : "" -%>
<% else -%>
<%= (record.authorized_for?(:action => link.crud_type) and link.action.to_sym != :enable) ? render_action_link(link, url_options) : "" -%>
<% end -%>
</td>
<% end -%>
Thank you for any help on this matter.

This answer is not specific to ActiveScaffold, but in Rails 3.2, the destroy link is generated as
<%= link_to 'Destroy', foo_instance, method: :delete, data: { confirm: 'Are you sure?' } %>
which results in the link having a data-confirm attribute, which does what it sounds like you want. Can you add this to your ActiveScaffold view?
UPDATE (Rails 2):
The data-confirm attribute is supported by jQuery (instead of, or in addition to prototype), so if you're using jQuery in a Rails 2 app, it might "just work". Otherwise, it's possible that you could just add javascript directly on the link you want to confirm. The url_options parameter for render_action_link looks juicy -- maybe it will accept arbitrary html attributes (as Rails link_to does), e.g.
url_options = { :onclick => 'return confirm("Are you sure?")` }
render_action_link(link, url_options)

Related

Rails - Proper way to select and submit from a list

I'm new to Rails and am trying to figure out the proper way to do this, but am having trouble finding an answer on Google. In my app, the user performs a search, which queries a 3rd party API and then displays a list of results for the user to choose from. When the user clicks the "Add" button for the result they want, I pass a hidden_field_tag that contains the API's ID to my controller and create a record in the database.
My questions are: Should I have a form for each result like my code below? Or should I use the link_to helper instead? Is there a better way?
Thanks.
My current code:
<% #series.each do |series| %>
<tr>
<td>
<%= form_tag({controller: "series", action: "create"}, method: "post") do %>
<%= hidden_field_tag(:series_id, series.xpath('seriesid').text) %>
<%= submit_tag("Add") %>
<%= series.xpath('seriesname').text %>
<% end %>
</td>
</tr>
<% end %>
You could use link to with post http method. For e.g.
link_to "Add", series_path(series_id: series.xpath('seriesid').text), method: post
(Change the param name and action to suit your need.)
Rails has js component converts this into a form submit automatically.

Rails using request.referer in testing

I have a helper method that has the following bit of code. It's part of an AJAX cart that's displayed on multiple pages on the site
module CartsHelper
def switch_buttons
unless URI(request.referer).path==new_order_path && !current_page?(store_path) \
|| current_page?(new_order_path)
#checkout = true
else
#checkout = false
end
end
end
Here's the cart partial view
<h2> Your Cart</h2>
<table>
<%= render(cart.line_items)%>
<tr class ="total_line">
<td colspan="2">Total</td>
<td class="total_cell"><%= number_to_currency(cart.total_price)%></td>
</tr>
</table>
<% if switch_buttons %>
<%= button_to 'Checkout', new_order_path, method: :get %>
<%= button_to 'Empty cart', cart, method: :delete,
confirm: 'Are you sure?', remote: true %>
<% else %>
<%= button_to 'Cancel Order', store_path, method: :get %>
<% end %>
The URI(request.referer).path is giving a bad argument (expected URI object or URI string) error in all of my tests. It works in the actual browser. I'm guessing it's because the tests don't actual go through the urls so request.referer is nil? Is there some way to set up the test to be able to get through this code?
Two things:
First, this answers your main question:
How do I set HTTP_REFERER when testing in Rails?
Second, it's not a given that request.referer will be set. Most browsers supply the header when you navigate from a previous page; most don't when you hand-enter a URL. HTTP clients can't be assumed to do so overall, and you have to be prepared to get nil from that attribute.

Working with each AND window.location on Rails

I have another question involving each loops. I have a view which displays a current classroom. It shows how many students are online atm, etc. Within a div located on the bottom right i have a table that lists all the available classrooms. The "name" of the classroom is a button which makes the page refresh with new parameters (:class_id) and then shows the "clicked" classroom.
My problem is identifying the proper ID for each row in the table within the each do loop.
I have this code in my view (Example)
<% #classrooms.each do |room| %>
<table>
<tr>
<td><%= room.id %></td>
<td><button onclick= "class()"><%= room.class %></button></td>
</tr>
</table>
<script>function class(){window.location = '<%= classroom_path(:class_id = room.id)%>'};</script>
<% end %>
Its redirecting with the new param, but the class_id is the same for all the entries (last one). Any help? This is probably fairly simple, not sure.
I'm confused. Why not use a real link ?
<% #classrooms.each do |room| %>
<%= link_to room.class, classroom_path(room) %>
<% end %>
If you don't want a link (which can be styled as a button with virtually any css framework; including bootstrap); you can always do :
<% #classrooms.each do |room| %>
<%= button_to classroom_path(room), method: :get, value: room.class %>
<% end %>
if you want to do it via js / jquery, here you go:
<% #classrooms.each do |room| %>
<%= tag :button, data: {url: classroom_path(room)}, class: 'js_button' ,value: room.class %>
<% end %>
<script type="text/javascript">
$(document).on('click', '.js_button', function(){
window.location = this.getAttribute("data-url");
});
<script>
also, typo: classroom_path(:class_id = room.id)
Your syntax looks wrong. Try
<td><%= room.id %></td>
And also <%= room.class %>
If you want to output data in erb, you need <%= not just <%`
Also, you are redefining the class() function for each #classroom object, so any button click would call the same function each time. You aren't making a new function for each instance.
But, this could all be cleaned up much easier by just doing a simple link_to and using path helpers like <%= link_to room.class, class %>

Hide the params hash and replace it with a cleaner URL

The default URL generated after a get request in Rails isn't very nice to look at.
Using the meta_search gem in a Rails 3 application, I've created a select menu to filter a list of articles by category. The code looks like this:
<%= form_for #search, :url => articles_path, :html => {:method => :get} do |f| %>
<%= f.label :category_name_equals, "Filter by category:" %>
<%= f.collection_select :category_name_equals,
Category.all(:order => "name"), :name, :name, :include_blank => true %>
<%= f.submit "Search" %>
<% end %>
<table>
<tr>
<th>Title</th>
<th>Category</th>
</tr>
<% for article in #articles %>
<tr>
<td><%= link_to article.title, article %></td>
<td><%= article.category.name %></td>
</tr>
<% end %>
</table>
Right now, when the form is submitted, a lengthy URL is returned containing the params hash:
http://localhost:3000/articles?utf8=%E2%9C%93&search[category_name_equals]=
Reviews&commit=Search
I want to keep the URL as clean as possible, for example:
http://localhost:3000/articles/category/reviews
or
http://localhost:3000/articles?category=reviews
What are some solutions to make the params hash URL more readable by humans?
You can't do that with a form with get method. it's an HTML issue.
You need add some Javascript to convert your URL to pretty URL or you can get URL in your controller in your rails application and redirect to your pretty URL.
Like shingara said, don't use a form at all. Instead use a list of links, and fancy things up with some css/js that makes your list behave/look like a drop-down menu:
<ul>
<% Category.all.each do |c| %>
<li>
<%= link_to(c.name, :controller => :articles, :action => :browse, :category => c.tag) %>
</li>
<% end %>
</ul>
For your routes, you'll want something like this, but DRYer:
routes.connect '/articles/browse/:category', :controller => :articles, :action => :browse
You can find many examples of CSS/JS dropdowns very easily: http://bit.ly/dRtQNd
You can find examples of good CSS/JS dropdown menus with considerably more effort ... unless you give up just ask for advice on stack overflow again :-). (Coding rudimentary versions of standard UI components from scratch is simple these days using jQuery and whatnot, so lots of people do it. Coding ones that "feel right" is actually very hard; fewer people do that!)
P.S. That form_for #search looks utterly weird. This is not what form_for #your_model_object was meant for...

How do I set a unique ID for checkboxes in a multi-record Rails form?

I've set up a Rails form roughly following the instructions in this Railscast.
Here's the code for the form:
<% form_tag complete_todos_path, :method => :put do %>
<ul>
<div id="incomplete_todos">
<% #incomplete_todos.each do |todo| %>
<%= render :partial => todo %>
<% end %>
</div>
</ul>
<%= submit_tag "Mark as completed" %>
<% end %>
And here's the code for the todo partial:
<div class="todo">
<li>
<%= check_box_tag "todo_ids[]", todo.id %>
<%=h todo.name %>
<%= link_to 'edit', edit_todo_path(todo) %>
<%= link_to 'delete', todo, :confirm => 'Are you sure?', :method => :delete %>
</li>
</div>
It's working great, but I'm looking to start implementing AJAX and I need each checkbox to have a unique id. Right now, the input tags generated look something like this:
<input id="todo_ids_" name="todo_ids[]" type="checkbox" value="7" />
Every check box has the same id ("todo_ids_"), which is a problem. I suspect the solution is embarrassingly simple, but I'm not seeing it. Any tips?
<%= check_box_tag "todo_ids[]", todo.id, false, :id => "todo_id_#{todo.id}" -%> or whatever you want the id to be.
I consider this a bug with check_box_tag caused by the seemingly hackish nature of manually giving it the name todo_ids[] and the method code calling sanitize_to_id(name). I just ran into this yesterday and I'm contemplating a patch.
I ended up using a solution similar to Ryan's, but as I wrote in the comment I had to make a further change. In the form:
<%= check_box_tag "todo_ids[#{todo.id}]", todo.id %>
In the action called by the form:
Todo.update_all(["completed_at = ?", Time.now], :id => params[:todo_ids].keys)
Note the "params[:todo_ids].keys" at the end, which was a workaround to deal with the odd way the parameters were formatted:
"todo_ids" => {"5"=>"5"}
Can you try this and let us know if it works:
check_box_tag "todo_ids[#{todo.id}]", todo.id %>
This is the expected behaviour of check_box_tag, as this comment on a rejected fix explains.
You can use collection_check_boxes like this (haml syntax, sorry):
# Accumulate todos in a params hash like { todos: { to_complete: [] } }
= collection_check_boxes(:todos, :to_complete, #incomplete_todos, :id, :name) do |todo_builder|
= todo_builder.label do
# This is the result of calling :name on the todo, as specified
# calling the helper
= todo_builder.text
= todo_builder.check_box
Of course you can use partials inside the block, just pass and use the builder inside.
Check more options in the API docs.

Resources