Let's suppose you have a basic menu like this one
And you want the Premium state (any boolean attribute) to change on click for a given local (any object).
A really neat way for doing these kind of things is through AJAX Calls, that is changing the state of the DOM tree without reloading the page.
Setting everything up
What I do is to write some specific routes for this, and I only want those routes to be accessible though AJAX and AJAX only. The following does the trick
#config/routes.rb Rails.application.routes.draw do class OnlyAjaxRequest def matches?(request) request.xhr? end end #rest of the routes end
We'll come to this later.
Now see the view
#app/views/show.html.erb ... <a href="" data-remote=true id="unique_id" class="premium-state"><%= local.premium %></a> ...
and notice the data-remote field, this is fundamental for what we want. It says to the controller that when we click this link, we don't want it to be sent to the regular HTML format procedure. Rather we want the JS one.
In the controller (mind this is just a quick way to write the controller method, but you should check for example, if the
update_attributes is successful
#app/controllers/locals.rb def set_premium local = Local.find params[:local_id] if local.premium #if local is premium, we set it to false local.udpdate_attributes(:premium => false) @message = "true" else #same thing for premium false end respond_to do |format| format.js end end
Now, when you respond with HTML you need to have a view in html format. Now you need one with
#set_premium.js.erb $("#unique_id").text("<%= j @message %>");
This code will be executed when you click the
unique_id link in the view.
We haven't even set the route for this action.
#config/routes.rb resources :locals do post 'set_premium' => 'locals#set_premium', constraint: OnlyAjaxRequest.new
There it is. The
constraint part indicates that this call has to be made through AJAX.
How do I call this route
Did you notice the
ROUTE_TO_YOUR_ACTION is the path that the
rake routes command pukes for that specific controller action.
A couple of remarks:
- the dataType field of the AJAX call is 'script'. Think of that as the AJAX requesting a script file and executing it.
typefield has to be consisting with the naming of the custom route.
aaaaaaand we're done.
And I think that's it. Your AJAX button should be working by now.
Feel free to point out any inconsistency in the article, so I can fix it/explain it.