Call action from view to and save the sent value - ruby-on-rails

I have a two buttons one with a value of true and the other with a value of false;
What I want, is on click to access a method in my application_controller (because here I have it at the moment) which is saving (in redis) the value of the click button, and navigate to the same page(but not with refresh because I'm using turbolinks and I don't want to load everything again).
How can I do something like this, I can probably create a action and make a post request with the value of the button and then use turbolinks to visit a location. But is this the best way, or there is a better way?

Basically if you are using Rails built in unobtrusive javascript driver you can create a button, link or form which asynchronously sends data by adding the remote:true option.
<%= button_to "Do Something", do_some_thing_path, id: 'do_something' remote: true %>
This requires that you have:
an actual route which the button (link or form) can GET, POST, PATCH etc to
a controller action linked to the route.
You can then listen for events with:
jQuery(function(){
$('#do_something').on('ajax:success', function(e, data, status, xhr){
// #todo handle success.
}).on('ajax:failure', function(e, data, status, xhr){
// #todo handle failure.
});
});
I recommend that you read the Rails Guides Working with JavaScript in Rails article for more info.

Related

Rails - go to index, but also submit form with the same click

I have a redirect that works fine for getting me to my index. It is below:
redirect_to action: :index, filters: { recent_price_change: "#{1.week.ago.strftime('%m/%d/%Y')} - #{Date.today.strftime('%m/%d/%Y')}" }, hide_filters: true
Thing is, I am populating a filter on click. On that same page is a button that is tagged with the submit action.
here is the excerpt of the HAML (it's sorta kinda like ERB... don't worry much on it, just note how it is type: submit) file containing it:
%button.btn.btn-primary.btn-sm{ type: 'submit', style: 'background-color: #a38672;' }
%span.glyphicon.glyphicon-play
Update List
Clicking the button above submits the form, which applies the filter put some results in a table on the screen.
This was/is all fine and good - but there is a new requirement where I want that submit button to be "automatically clicked" on redirect. AKA, I don't want to have to click this button manually ... instead, as part of the redirect, the form needs to be submitted. So when the page loads, it is AS IF I had just clicked the button - the data is populated, etc. Do you all know if this is possible/how I would do it? I have dug through documentation for the redirect_to action hoping I would find some help there - but no dice as of yet.
UPDATE:
I added:
document.querySelector('.button.btn.btn-primary.btn-sm').click();
Onto the haml at the end of the file like so:
:javascript
document.querySelector('.button.btn.btn-primary.btn-sm').click();
It does submit the form on load... but turns out my index page must be getting re-rendered over and over... it repeatedly clicks the button. It doesn't do it just once. Was wondering if there is some way to bind this just to onload.
UPDATE 2:
So I wrote
firstSubmit = function() {
document.querySelector('.button.btn.btn-primary.btn-sm').click();
};
$(document).on('page:load', firstSubmit);
The problem is... seems my page is reloading itself repeatedly. So then, it spams my button over and over, leading to total flux of the page. Anyway to limit this without getting really janky (global var? - I'd hate to)?
You may add flag variable to form (assume form action redirects to index):
= hidden_field_tag :do_not_redirect
%button.btn.btn-primary.btn-sm{ type: 'submit', style: 'background-color: #a38672;' }
%span.glyphicon.glyphicon-play
Update List
Then modify javascript:
- unless params[:do_not_redirect]
:javascript
$(document).on('page:load', function () {
$('#do_not_redirect').val(1);
$('.button.btn.btn-primary.btn-sm').click();
});
And controller:
redirect_to action: :index, filters: {
recent_price_change: "#{1.week.ago.strftime('%m/%d/%Y')} - #{Date.today.strftime('%m/%d/%Y')}"
}, hide_filters: true, do_not_redirect: params[:do_not_redirect].presence
I think what you want to do is utilize a callback. Not sure if you're familiar, but a callback is just a routine that you run after some other action has taken place. In this case, after you click the submit button (which would most likely be an after_save or after_commit callback), you want to redirect to the index. Callbacks are generally found at the top of the controller in a case like this, something like the following:
class SomeController < ApplicationController
after_save :go_to_index
Then, after your normal controller actions:
private
def go_to_index
// Redirect code
end
I think this is what you're looking for, you can find the callback api info here: http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html.

Autosubmit a language dropdow in Rails 4

I'm wondering how to get a dropdown that switches the page's language to work. I currently have the following:
<%= select('locale', 'id', %w(English Español Italiano 日本語 한국어), :onchange => "this.form.submit()") %>
Any idea how I can get this to switch the page's locale?
I am currently passing the locale via the params hash.
There are several problems:
You're trying to submit a select box..... but where does it submit to?
How are you managing the languages on your page?
--
When submitting with JS, you have to remember that it needs to somewhere to submit to.
Like a <form>'s action attribute, your JS needs a location to send the submit request. This is normally handled with a form, but can also be manually inputted with Ajax.
You may wish to use this:
#app/assets/javascripts/application.js
$(document).on("change", "select", function(e) {
$.ajax({
url: "your/url",
data: $(this).value(),
success: function(data) { ... },
error: function(data) { ... }
});
});
This will take the inputted value of the select box and send the data to a preformatted route in your Rails app. This leads nicely onto my second question -- how you get the language to remain in the app...
-
Regardless of your structure, you'll need to give your Rails app a way to determine the language you have selected.
If only to set a session variable, you have to pass your data through to your Rails controller.
To do this, you first need to ensure you have the routes and then the controller action required to handle the request:
#config/routes.rb
post :language, to: "application#language"
#app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
def language
session[:language] = params[:language] #-> this needs to be refactored
end
end
You'll then be able to pass back some response or command to invoke the language change on the page.
Although setting the language in the backend, as described above, may seem tedious, doing so will give you the ability to set the entire language parameter for the site -- IE if you wanted to use it for currency etc, it will be available in all the actions you need.
Hope this helps.

How to get rails to use ajax to update an HTML table row after the db update?

I have a table of content with multiple rows.
For any given row I want to be able to verify a record and have that be reflected immediately on the screen by changing the "verify link" hyperlink to be just plain text 'verified'.
Seems like a fairly common pattern for others.
I have the following markup:
...# (table stuff).
= link_to 'verify', verify_link_path(:id => link.id), class: 'verify', remote: true
This (successfully) calls the links controller 'verify_link' method:
def verify_link
#link = Link.find(params[:id])
# Ignore additional verify logic for now, just set as verified (when the user clicks verify).
#link.verified_date = Time.now
#link.save!
respond_to do |format|
format.js
end
end
I know this works... because the database gets updated.
Finally I want to update the page (table-row-cell) to reflect this.
This is where I am stuck.
The controller method successfully calls the following app/views/links/verify_links.js.erb file:
$(function() {
$(".verify")
.bind("ajax:success",function(event,data,status,xhr) {
this.text='verified';
alert("The link was verified.");
});
});
I know it gets invoked... because I can put alert("hello world"); at the start and it gets displayed as a pop-up.
The part that isn't working is replacing the 'verify' link with plain text 'verified'.
Actually I can't even the alert to work in there at all.
Nothing gets updated in the ui. On the backend the change in the db is made however, so if I refresh the page I do see the change reflected at that point).
Notes:
Is there an issue with the fact that there are multiple links? i.e. Should I be using an id, which I would have to munge from the table row id or number
app version is rails 3.2.17 with the asset pipeline.
app was originally written in rails 2 and was later upgraded.
I am using jquery 1.7.2 and rails.js but avoiding frameworks like angular, ember, etc. initially as I want to learn more of the lower level stuff first. Once I do I will then use a framework.
#hjing is right. The code inside app/views/links/verify_links.js.erb is already a response to your ajax. You need not bind it to the ajax:success.
As you suggested you need to make an id for each link which you'll have to munge from the table row id or number. For example for your your links will look like this:
= link_to 'verify', verify_link_path(:id => link.id), class: 'verify', id: "verify_#{table_row_no}", remote: true
then inside your app/views/links/verify_links.js.erb you can target that particular link like this:
$("#<%= j 'verify_#{table_row_no}' %>").text("verified");
$("#<%= j 'verify_#{table_row_no}' %>").prop("href","#"); #you would also want to change the href in case someone clicks it again

ajaxSetup not working with Rails / jquery-ujs

I'm working on a project that makes heavy usage of XHR, and there is some data that needs to be appended to each ajax request in order for the server side to properly keep track of what is going on in the browser.
I have a generic class called xhr_response_handler than I use to handle the callbacks for all ajax requests that is added to all forms, links etc that is making ajax requests. (i.e. where ":remote => true" in rails)
$('.xhr_response_handler')
.on('ajax:success', function(event, data, status, xhr) { xhr_success(data); })
.on('ajax:failure', function(xhr, status, error) { xhr_fail(error); });
Then I try to append the default data sent with each request using:
$.ajaxSetup({
data: {
Foo: <%= #Bar %>
}
});
This works for some of the elements where the ajax settings are configured directly with jquery, but this does not work for some elements created using rails methods like link_to and form_for with :remote => true.
The odd thing is that if I also add
$('.xhr_response_handler').data( 'params', { Foo2: <%= #Bar2 %> } );
Then that works for adding data to the rails generated ajax requests using link_to. What makes it odd is that now all of a sudden the ajaxSettings also works, and in the ajax requests I get both Foo and Foo2 as parameters. But I get no parameters at all when using ajaxSettings by itself.
Furthermore, none of the data to be appended gets serialized into the form data sent in ajax requests generated from the rails form_for method.
Any help would be appreciated.
Rails 3.2.3
Ruby 1.9.3p194
jQuery 1.7.2
I think this behaviour appears because the data hash of $.ajaxSetup is overridden by the ajax calls you do later on. The data has to be merged manually.

How do you send a request with the "DELETE" HTTP verb?

I'd like to create a link in a view within a Rails application that does this...
DELETE /sessions
How would I do that.
Added complication:
The "session" resource has no model because it represents a user login session. CREATE means the user logs in, DESTROY means logs out.
That's why there's no ID param in the URI.
I'm trying to implement a "log out" link in the UI.
Correct, browsers don't actually support sending delete requests. The accepted convention of many web frameworks is to send a _method parameter set to 'DELETE', and use a POST request.
Here's an example in Rails:
<%= link_to 'log out', session_path, :method => :delete %>
You may want to have a look at Restful Authentication.
I don't know about Rails specifically, but I frequently build web pages which send DELETE (and PUT) requests, using Javascript. I just use XmlHttpRequest objects to send the request.
For example, if you use jQuery:
have a link that looks like this:
<a class="delete" href="/path/to/my/resource">delete</a>
And run this Javascript:
$(function(){
$('a.delete').click(function(){
$.ajax(
{
url: this.getAttribute('href'),
type: 'DELETE',
async: false,
complete: function(response, status) {
if (status == 'success')
alert('success!')
else
alert('Error: the service responded with: ' + response.status + '\n' + response.responseText)
}
}
)
return false
})
})
I wrote this example mostly from memory, but I'm pretty sure it'll work....
Correct me if I'm wrong, but I believe you can only send POST and GET requests with a browser (in HTML).
Rails' built in method for links will generate something like this:
Logout
If you don't want to use the Rails' built in method (i.e. don't want the rel="nofollow", which prevents search engine crawlers from following the link), you can also manually write the link and add the data-method attribute, like so:
Logout
Browsers can only send GET/POST requests, so this will send a normal GET request to your Rails server. Rails will interpret and route this as a DESTROY/DELETE request, and calls the appropriate action.

Resources