ajaxSetup not working with Rails / jquery-ujs - ruby-on-rails

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.

Related

Call action from view to and save the sent value

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.

Ruby on Rails: Using user input for calculations on the same page

So, I'm having issues with what I think is a really simple problem. I don't know how to access user input...or perhaps I don't know how to declare a temporary variable in rails.
Anyway, what is the most straight forward way of accomplishing this:
<div>
Enter Group Size: <%= number_field_tag(:group_size)%>
Select Study Site: <%= number_field_tag(:site) %>
</div>
<% if :site > 4 %>
Hello!
<% else %>
Nope!
<% end %>
I suppose I'll need javascript to actually make it work, but for now I just need to know how to use these variables.
Any help would be greatly appreciated. Thanks.
To use them dynamically with ERB, they need to be wrapped in a form and submitted to the server. You can then access them easily with params[:variable_name]. It would probably be cleaner to prepare the message in the controller, but if you don't need to interact with models, it would be more straightforward to use some basic JS to do everything.
As with most things, the solution is a lot more involved:
Ajax
Unlike native apps, Rails relies on the HTTP protocol
HTTP works on requests. You send requests to a server to render a web page; the server responds to the requests. The problem with this is you cannot use Rails with "live" functionality without sending requests to-and-from the server (even "live" applications just keep a perpetual connection open, acting as a single request)
This means if you want to process "live" data (without refresh), you'll have to use a technology to send a request on your behalf. As you noted, this will be ajax:
$(".element").on("action", function(){
$.ajax({
url: "your/end/point"
data: {your: data}
success: function(data) {
alert(data)
}
});
});
Rails
To handle an ajax request in Rails, it's basically the same as handling an HTTP request:
#config/routes.rb
resources :controller do
get :your_endpoint
end
#app/controllers/controllers_controller.rb
def your_endpoint
# perform actions here
respond_to do |format|
format.html
format.js { # handles JS / Ajax request }
end
end
Return
You can then handle the returned data with your JS (Ajax) function. This gives the image that it's working in "real time", but will actually be sending & receiving requests from the server every time

How do I pass multiple objects to the Rails controller action "create" via JSON?

As you can probably tell by this question, I am a newbie to both Ruby on Rails and Knockout.
I'm trying to build a RoR web app that will allow a user to pull up their assets data which is stored in a MySQL database, edit that data using Knockout on the front end, and then use Knockout to send the revised data back to the server via Ajax to Rails.
At this URL here: http://knockoutjs.com/documentation/observableArrays.html
it says:
The convention in Rails is that, when you pass into an action a JSON object
graph, the framework can automatically convert it to an ActiveRecord object
graph and then save it to your database. It knows which of the objects are
already in your database, and issues the correct INSERT or UPDATE statements.
I've tried doing Google searches and I haven't found anything that makes it clear to a newbie like myself. So I'm asking this question here.
In Knockout.js, when the user submits, they will be triggering a function "saveAssets" which will send the data in JSON format to "/assets" on the Rails app. The idea is that "self.assets()" will contain multiple instances of Asset objects.
self.saveAssets = function() {
$.ajax('/assets', {
data: ko.toJSON({ assets: self.assets() }),
type: "post",
contentType: "application/json",
success: function() { console.log('hella') }
});
};
When that function executes, here is the JSON that gets posted to the Rails server. Most of the Asset objects have id values, which means they are already in the server and I just want to update them, but there's also one new Asset record without an id number:
{"assets": [
{"id":1,"desc":"DWS Investments Roth IRA Mutual Fund","shares":"810.577","symbol":"SCQGX","price":"41.17","total":"33371.46"},
{"id":2,"desc":"DWS Investments Money Market Fund","shares":"20000.00","symbol":null,"price":1,"total":"20000.00"},
{"id":6,"desc":"credit card debt","shares":"-8700.00","symbol":null,"price":1,"total":"-8700.00","_destroy":true},
{"shares":"0.00","symbol":"","price":1,"total":"0.00"}
]}
And here's the Ruby on Rails controller action code:
def create
respond_to do |format|
format.json {
#assets = params[:assets]
#assets.each do |this_asset|
#a = Asset.new(this_asset)
#a.save
end
}
end
end
What am I supposed to be doing in the "create" action in order to receive the JSON array, parse it into individual "Asset" objects and save/update them to the database?
Thanks for your help!

Is it possible to send javascript request using wiselinks?

By default rails (I am using rails 4) sends data-remote requests with the following header:
Accept:*/*;q=0.5, text/javascript, application/javascript, application/ecmascript, application/x-ecmascript
Later in rails code I respond to it using format.js.
I want to migrate to wiselinks, but all data-push requests try to render html.
Is it possible to have default rails behaviour with wiselinks?
I think that you don't unserstand correctly how Wiselinks work. If you use :data => { :remote => true }, then you simply don't need :data => { :push => true }.
Pushing should be used only if you need to update your URL (follow a link).
Ok, I rewritten my controllers to respond to html AJAX requsets instead of using JS requests.
This way I can use wiselinks and it works. Main reason I was using JS response is to set page title with javascript and some other details. But with wiselinks I can use special helper for that.
I think there may be a need in the future to implement some complex behaviour after AJAX request, which will require some JS execution on client side after the response. However this will be possible to implement with page:done event
Thank you all for the help!

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