Rails link_to :confirm for a specific page - ruby-on-rails

I'm new to Ruby on Rails and would like to know that, if there is a way to strict link_to :confirm for a specific page. Because I'm putting this in every page, but I don't want it to show a confirm message in every page.
I'm adding the code here as well, but the formate it's incorrect in the textbox.
link_to "Home",'/', :confirm => 'Clicking OK Will Discard Any Unsaved Changes. Click Cancel To Return To The Home Page.'

You can make a helper like this to restrict by controller_name and action:
def link_home(link_options = {})
unless controller_name.eql?('some_controller') and action_name.eql?('some_action')
link_options.merge!{:confirm => 'Clicking OK Will Discard Any Unsaved Changes. Click Cancel To Return To The Home Page.'}
end
link_to "Home",'/', link_options
end

Related

Rails - Change boolean value on link click

In my app I have user notifications where the user gets notified for certain actions. These notifications are being shown in a dropdown from the navbar (like Facebook or S.O.). All of the notifications have a boolean attribute called :read and are default set to false. I'm using bootstrap with the dropdowns (in case that helps).
I want to create a method where when the user clicks to open the dropdown, all of their unread notifications become read.
Here is what I have so far for the method.
def read_notifications
PublicActivity::Activity.where(recipient_id: current_user).where(read: false).update_all(:read => true)
end
This updates all of the current user's notifications to :read => true when the method is called. In the view here is what I had so far for the dropdown link.
<%= link_to read_notifications_path, :class => "dropdown-toggle notifications_icon", :'data-toggle' => "dropdown", :controller => "application", :action => "read_notifications", :method => :post do %><% end %>
and the routes.rb I had this.
match "/read" => "application#read_notifications", :as => "read_notifications", via: 'post'
Now I know what I have is wrong, but even so when I click the link it does switch all of the user's notifications to read, it just acts also as a link (duh) and goes to a different page.
As you know, the link on a bootstrap dropdown is "#".
Does anyone know how I can set this up properly where when the user clicks the notification link in the navbar, ALL it does is open the dropdown and change the boolean value to true for all notifications.
I know this is possible, I just haven't been able to figure it out yet.
Thanks for taking a look at it.
EDIT
JS file
$(".notifications_icon").on("click", function(){
$.post("/read", function(data){
$('.notification_badge').text("");
});
});
View
<%= link_to "#", :class => "dropdown-toggle notifications_icon", :'data-toggle' => "dropdown" do %>
<span class="notification_badge"><%= find_unread_notifications_count(current_user) %></span>
<% end %>
This is Posting to the /read to read all of the notifications but it's not updating the count
You want a dash of unobtrusive JS. For example, SO has a class js-inbox-button that, when clicked, triggers updates on unread counts (both client and server). I won't dig into their JS source, but it's fairly simple to build.
You seem to already have a relevant class (notifications_icon), though you might want to use something else. When the link is clicked, use jquery $.post.
$(".notifications_icon").on("click", function(){
$.post("/read", function(data){
// remove unread count
$('.notification_badge').text('');
});
});
Now this is a very basic implementation. Couple of suggestions:
Only make requests when necessary (check for unread count on page first)
Use a data attribute on the link to pass /read path. That way you can still use your path helpers instead of hardcoding a path.
Store the above JS in a separate file (unobtrusive)
AJAX.
By adding remote: true you're starting with AJAX. Now the call goes to your path, and nothing happens! yay!
You want something to happen, though. So in your controller (I wouldn't do it in the application_controller, if I were you... activities_controller.rb maybe?):
controllers/activities_controller.rb
def read_notifications
PublicActivity::Activity.where(recipient_id: current_user).where(read: false).update_all(:read => true)
respond_to do |format|
format.js
end
end
You're on your way to Asynchronous loading! Now you need a js file to match it. So, since you've already moved this action to the activites, in your view, you'll have a new js.erb file to create (notice that it's in the same folder in the views as the controller name, and the file is named after the action):
views/activities/read_notifications.js.erb
$('#your_menu_div').html("<%= j render partial: 'activities/notifications' %>");
Now you create a partial (views/activities/_notifications.html.erb) that gets rendered into your pulldown menu.
Clear as mud?

Rails Cancel Confirmation Reason

I have an application, which contains calls. I want to be able to cancel the call and supply a reason for the call cancellation. So far I have my cancel action working in the controller, but I'm trying to figure out how to expand it so before it posts "cancel" to the call_status field it will also populate a cancel_reason field based on a drop down.
Here's what I have so far:
view code: cancel button
<%= link_to 'Cancel',
cancel_call_path(call),
confirm: 'Are you sure you want to cancel the call?',
:method => :post,
:class => 'btn btn-danger btn-mini' %>
controller code: cancel action
def cancel
#call = Call.find(params[:id])
attrs = {
call_status: 'cancel',
incharge_id: #call.units.first.incharge_id,
attendant_id: #call.units.first.attendant_id
}
attrs.merge!({ incharge2_id: #call.units.second.incharge_id, attendant2_id: #call.units.second.attendant_id }) if #call.units.count == 2
if #call.update_attributes(attrs)
#call.units.each do |unit|
CallMailer.cancel_call(unit.incharge, #call).deliver
CallMailer.cancel_call(unit.attendant, #call).deliver
end
redirect_to calls_url, :notice => "Call was successfully cancelled"
else
redirect_to calls_url, :error => "Whoops."
end
end
I want either the confirmation pop-up shown, with the reason for cancellation, or the cancel action tied to a different view with a small form, that includes a reason.
By default the confirm attribute in link_to uses a JavaScript window.confirm which is a simple yes/no that returns true/false.
If you want to do it all on the same page you You'll need to use JavaScript and Ajax to accomplish this. Something along the lines of adding an event handler on the Cancel link that will show a modal with a drop down. The result of this modal will then Ajax a POST request to the Rails app. There are a lot of jQuery Plugins that you can use to help you accomplish this in Rails.
The second option is the one you described which would be to use a separate action in your controller. In terms of UX I think the first option is a better route to go and isn't as scary as it sounds.

UJS - where do I put the js.erb?

My articles can appear on several sites, so as well as an article model with title, body etc and a site model with site_id, site_name etc, I have I have an article_site_permission model, with article_id, site_id and visible which can be either true or false.
On my article edit page, I've done a button_to:
<%= button_to 'Hide', article_site_permission_path(:id => #article_site_permission_id, :article_site_permission => {:visible => "false"}), :method => :put %>
This works - it changes the permission to false. And I can show the Show button which does the reverse.
Now I want to refresh the div that has the button in it by adding :remote => true to the button link. But where do I put my javascript?
Is it in the article_site_permission view - even though I'm looking at a view of the article itself?
Is it called update.js.erb?
Thanks for your help.
Update for clarity.
My button is on the articles/edit page. The button updates article_site_permissions. I want to go back to articles/edit and refresh the div that has the button in it.
I must edit the update controller for article_site_permissions, but where do I put the js to refresh the div?
In your controller, redirect to the action you want (index, show, etc.). Do a
respond_to do |format|
format.js
end
under that action in your controller. Then, in the corresponding view, have a file named
index.js.erb
Or replace index with whatever action, just be sure to give it the same name as the action that's calling it.
EDIT
I should also mention you are correct in adding the remote true to your button. It's hard to tell from your question what action you're trying to reach in which controller. If you're trying to access the show action of the ArticleSitePermission controller, you're doing well. However, it seems like you're not trying to route to show. Check out this link for more info on routing to different actions.
EDIT 2
This should do it.
<%= link_to 'Click me', {:controller => "article", :action => "update", :id => #article_site_permission_id },
:remote => true %>
Also, if all you want to do is redirect to the article, you don't need to do js. Just redirect to articles#show

Rails 3 - remote delete

In an ERB Rails view
<%= link_to("Destroy", foos_path(1), :method => :delete, :confirm => "Are you sure?") %>
With a link_to like the above you can process the delete for a foo with an ID of 1.
How do make it remote and (a) still control being redirected to a page of my control or (b) call custom JavaScript (the goal of which would be jQuery to refresh a list)
Add :remote => true to the link_to will create a remote link.
In your controller method at the end put
respond_to do |format|
format.js { render "my_method"}
end
You can omit the name of the ajax file if it's the same name as the method.
In my_method.js.erb simply call javascript functions, and you can embed erb ie:
$("#someDiv").load(<%= #some_value $>);
You can redirect to another page using standard javascript/jquery if you choose.

Popup/New Window + Redirect_to + Rails

It is possible to redirect_to some url from the controller and open the url in the new window at the same time ?
Not really from the controller action.
A redirect is an HTTP response with a 301/302 status code and an empty body in Rails. As the body is empty, you don't have any way to include extra processing for the browser (such as javascript etc to open a new window).
Assuming you have the the controller action triggered via a hyperlink on another page, your best bet would be to have that open in a new window. Then the redirect target would be displayed.
Either that, or render the same page again as a regular response (no redirect), and insert some javascript when the page loads to open a new window
#madlep "your best bet would be to have that open in a new window"
Thanks for that one. Works perfectly!
view:
<%= link_to "Buy this product", buy_path, target: "_blank" %>
controller:
def buy
...
redirect_to link
end
Searched a little and found a solution... it's not on the controller (as I originally wanted too but it's quite easy...) in your view:
<%= link_to '', {:controller => 'assignments', :action => 'overall_report_gen', :evaluator_relations => #evaluator_relations}, :target => '_blank', :id => 'reporte' %>
<script language="JavaScript">
document.getElementById('reporte').click();
</SCRIPT>
so, with '' as the display string in the link_to, you get an invisible link,
with the :target => '_blank' the link, when clicked will open in a new window
and the :id => 'reporte' is needed in order to click the link with javascript.
so just place the same id in the link_to and in the string in the javascript, and that's it
remember to place the javascript snippet AFTER the link_to so as to wait the element is loaded

Resources