Rails link_to generating error on page loading - ruby-on-rails

I have the following code in my view:
<% if #user.marine? %>
<div>
<%= link_to("Close account".html_safe, deactivate_path(#user), method: :patch,
html_options = { role: "button", class: "button-small", data: "Are you certain?"
}) %>
</div>
<% end %>
On loading the page on the development server, this generates the error below, referring to the <% end %> line.
syntax error, unexpected ')', expecting => })
);#output_buffer.safe_append= syntax error, unexpected
keyword_end, expecting ')' '.freeze; end
Anyone got an idea what in the link-code is causing the error and how I should adjust for it?
I think it has to do with the data: "Are you certain?" part. This should pop-up a confirmation message. I also tried confirm: "Are you certain?" instead but that made no difference.
Update: I can't get the link to work unless I remove the entire html_options part. Just removing the data: "Are you certain?" part is not sufficient.

It is a hash key, there should be : or => instead of =. Try the following, grouping all html_options in one hash like this:
<%= link_to 'Close account'.html_safe,
deactivate_path(#user),
{ method: :patch, role: 'button', class: 'button-small', data: { confirm: 'Are you certain?'} } %>

Related

link_to confirm not working with controller/action

UPDATE - I just checked and NEITHER confirm is working.
I need to have a confirm on a link_to. I've tried a couple of variations on the data/confirm attribute but it is bypassing the confirm dialog.
My link is
<%= link_to 'new bs line',
:controller => :bedsheet_lines,
:action => :create_new_bedsheet_line,
:data => {:confirm => 'Are you sure that you want to export the Bedsheets?'} %> <br>
That does not work, but a regular link_to does: and neither does this
<%= link_to "Export Data as a CSV file ",
slitter_bedsheet_export_path(format: "csv"),
:data => {:confirm => 'Are you sure that you want to export the Bedsheets?'} %> <br>
If I do an inspect, the link that won't show the confirm looks like
<a href="/bedsheet_lines/new_bedsheet_line?
data%5Bconfirm%5D=Are+you+sure+that+you+want+to+export+the+Bedsheets%3F">
new bs line</a> <br>
Whereas the link that does show a confirm looks like Nor dies this work.
<a data-confirm="Are you sure that you want to export the Bedsheets?"
href="/csv_export.csv">Export Data as a CSV file </a> <br>
My suspicion is that the problem is that confirm will not work when your link_to specifies and action and controller. If that is true, I should be able to find a way to work around that. Now I'm not sure where my problem lies.
Not sure why the hash syntax matters but I use
<%= link_to 'text', path(param), data: { confirm: 'confirmation' } %>
Edit:
Specifying controller and action it would be:
<%= link_to 'text', { controller: 'bedsheet_lines', action: 'create_new_bedsheet_line' }, data: { confirm: 'confirmation' } %>

Route using dot rather than / in rails DELETE method

The delete button I have in my rails app returns the following error :
No route matches [DELETE] "/requests.3"
I'm not sure why.
Here is the button link in the request view (using bootstrap 3) :
<%= link_to '<i class="glyphicon glyphicon-remove"></i>'.html_safe,
requests_path(request), method: :delete,
data: { confirm: 'Are you sure?' }, class: 'btn btn-danger' %>
and in routes I have :
delete 'requests/:id' => 'requests#destroy'
and in the controller I have
def destroy
#request = Request.find(params[:id])
#request.destroy
redirect_to action: 'index', status: 303
end
Any help would be appreciated.
Thank you.
The solution I figured to work was to manually specify the path in the <%= link_to tag
<%= link_to '<i class="glyphicon glyphicon-remove"></i>'.html_safe,
"/requests/#{request.id}/destroy", method: :delete,
data: { confirm: 'Are you sure?' }, class: 'btn btn-danger' %>
and that seemed to work.

Render output of multiple expressions in one ERB block

I have a helper that looks like this:
if current_user.find_voted_items(vote_scope: :inspired).include?(post)
link_to vote_inspired_post_path(post, vote_scope: :inspired), method: :post, data: { confirm: 'Are you sure this post Inspires you?' }, class: "btn btn-default" do
"<i class='fa fa-lightbulb-o'></i> <br />Inspired".html_safe
end
link_to vote_happy_post_path(post, vote_scope: :happy), method: :post, data: { confirm: 'Are you sure this post makes you happy?' }, class: "btn btn-success" do
"<i class='fa fa-smile-o'></i> <br />Happy".html_safe
end
link_to vote_disappointed_post_path(post, vote_scope: :disappointed), method: :post, data: { confirm: 'Are you sure this post disappointed you?' }, class: "btn btn-info" do
"<i class='fa fa-meh-o'></i> <br />Disappointed".html_safe
end
link_to vote_upset_post_path(post, vote_scope: :upset), method: :post, data: { confirm: 'Are you sure this post upsets you?' }, class: "btn btn-inverse" do
"<i class='fa fa-frown-o'></i> <br />Upset".html_safe
end
end
I need all the links and their nested <i> tags to be rendered - but for some reason, this version is just rendering the last line.
All of that is inside a method called show_vote_buttons(post), that is being called like this in the view: <%= show_vote_buttons(#post) %>
What's the best way to tackle this?
Basically, the reason behind this is that <%= %> renders the output of show_vote_buttons method. This method doesn't explicitly return anything, so the last evaluated expression is returned, in your case, the last link_to output.
In a general case, if you have not used a helper method and just pasted it's body instead with multiple link_to calls, you would get the same behavior. The reason is similar: <%= %> does not render each link_to, it executes code inside <%= %> and then outputs the result of last evaluated expression.
I see two different approaches to change the output:
Helper method: concatenate the output of all evaluated expressions and print as one string:
1.1 using << and parenthesis () around each link_to;
1.2 creating a string with double quotes " and interpolating each link_to output with #{} in it;
1.3 using concat;
Partial views: build a separate view from your existing helper method and use <%= %> to output each link_to.
P.S. After testing all four methods I've come to a conclusion (here comes a personal opinion) that the second method is more preferable, at least because it keeps rendering in the views and avoids concatenation that can look messy. Similar approach is used, for example, in the Devise gem, where all shared links are located in the app/views/devise/shared/_links.html.erb partial.
but for some reason, this version is just rendering the last line.
That reason is because in Ruby, if a method doesn't have an explicit return, then the returned value of a method is the value of the last line that got executed before a method exited. If you want to return multiple values from a method, use the return keyword and comma-separate your values.
#will return an array [1,2,3]
def some_method
return 1,2,3
end
Also, I do agree with the other answers that your code should be more DRY, but I was simply trying to clarify your original question.
Have a try with this code
if current_user.find_voted_items(vote_scope: :inspired).include?(post)
concat(link_to vote_inspired_post_path(post, vote_scope: :inspired), method: :post, data: { confirm: 'Are you sure this post Inspires you?' }, class: "btn btn-default" do
safe_concat(content_tag(:i, "Inspired", calss: "fa fa-lightbulb-o"))
end)
concat(link_to vote_happy_post_path(post, vote_scope: :happy), method: :post, data: { confirm: 'Are you sure this post makes you happy?' }, class: "btn btn-success" do
safe_concat(content_tag(:i, "Happy", calss: "fa fa-smile-o"))
end)
concat(link_to vote_disappointed_post_path(post, vote_scope: :disappointed), method: :post, data: { confirm: 'Are you sure this post disappointed you?' }, class: "btn btn-info" do
safe_concat(content_tag(:i, "Disappointed", calss: "fa fa-meh-o"))
end)
concat(link_to vote_upset_post_path(post, vote_scope: :upset), method: :post, data: { confirm: 'Are you sure this post upsets you?' }, class: "btn btn-inverse" do
safe_concat(content_tag(:i, "Upset", calss: "fa fa-frown-o"))
end)
end
Note: Didn't tested it.
The reason is perfectly explained by #suslov around this answer. Metaprogramming might keep code DRY:
DATA = {
inspired: { ico: 'fa-lightbulb-o',
msg: 'Are you sure this post Inspires you?',
btn: 'btn-default' },
happy: { ico: 'fa-smile-o',
msg: 'Are you sure this post makes you happy?',
btn: 'btn-success' },
... }
if current_user.find_voted_items(vote_scope: :inspired).include?(post)
DATA.map do |k, v|
instance_eval %Q{
link_to vote_#{k}_post_path(post, vote_scope: :#{k}),
method: :post,
data: { confirm: #{v[:msg]} },
class: "btn #{v[:btn]}" do
"<i class='fa #{v[:ico]'></i> <br />#{k.capitalize}".html_safe
end
}.join($/) # return them all, concatenated with separator
end
end

rails 4 update_attribute with unobtrusive javascript

I have the following link which is generated in loop
<% if category.status %>
<%= link_to 'Disable', edit_category_path(category), method: :get, remote: true, confirm: 'Are you sure you want to disable' %>
<% else %>
<%= link_to 'Enable', edit_category_path(category), method: :get, remote: true, confirm: 'Are you sure you want to enable' %>
<% end %>
In my edit action I have
unless params[:id].blank?
#category = #category.update_attribute(:status, false) # Here I mentioned false as static.
end
If I click enable it should enable(update as true in database) and if I click disable it should disable(update as false in database)
How can I do it. How do I pass the status(true or false for updation)
Use it like this
<%= link_to 'Disable', edit_category_path(category, {status: 0}), method: :get, remote: true, confirm: 'Are you sure you want to disable' %>
And you can call as
params[:status] in controller
If 'GET edit_category_path' is the usual 'produce a form which POSTs to #update,' the GET shouldn't update server state.
Maybe POST (probably directly to #update), to change status, then GET the edit_... path
Or POST to a new action that updates status and redirect to #edit?

How to add form parameter in Rails link with PUT method?

Right now, I have the following and it works:
<%= link_to 'stop service', service_path(:id => #service.id, 'service[stopped]' => true, method: :put, data: { confirm: 'Are you sure?' } %>
The link looks like this: http://localhost:3000/services/1?service%5Bstopped%5D=true
So the service[stopped] parameter gets submitted to the server as part of the query string. I need it to get submitted though as a POST/PUT form parameter instead. I tried adding 'service[stopped]' => true inside the data hash, but that didn't do anything.
You can try this.
<%= link_to 'stop service', service_path(:id => #service.id, 'service[stopped]' => true, data: { confirm: 'Are you sure?' }) , :method => :post %>
You can refer Rails 3 link_to generator for :post, :put, & :delete?

Resources