I've got a little demo setup in which clicking a checkbox toggles an attribute via AJAX. It's working fine, but Rails REALLY wants to render something, so I've basically resorted to creating a blank toggle.js.erb file in my views.
Controller action in question:
def toggle
@task = Task.find(params[:id])
respond_to do |format|
format.js do
if (@task.status != true)
@task.status = true
else
@task.status = false
end
@task.save
render :layout => false
end
end
end
View in question:
<h1>Tasks</h1>
<ul style="list-style-type: none;">
<% @tasks.each do |task| %>
<li id="<%= dom_id(task) %>">
<%= check_box_tag(dom_id(task), value = nil, checked = task.status) %>
<%= task.action %> <%= link_to 'Edit', edit_task_path(task) %>
<%= link_to 'Delete', task, :confirm => 'Are you sure?', :method => :delete, :remote => true %>
</li>
<% end %>
</ul>
<%= link_to 'New Task', new_task_path %>
<script>
$$('input').each(function(el) {
el.observe('click', function(event) {
// Get the task ID
var elId = el.id.split("_")[1];
// Build the toggle action path
var togglePath = '/tasks/' + elId + '/toggle/';
// Create request, disable checkbox, send request,
// enable checkbox on completion
new Ajax.Request(togglePath, {
onCreate: function() {
el.disable();
},
onSuccess: function(response) {
},
onComplete: function() {
el.enable();
}
});
});
});
</script>
Without the blank toggle.js.erb file I've got in the views, Rails still gives me an error saying that it's trying to render something.
Ultimately, I'd like to both not have to have a blank toggle.js.erb file, and I'd like to get that Prototype stuff into my static JavaScript stuff and out of the view.
I'm pretty new to Rails, so there's probably an easier way to be doing this, but I'm kind of stuck here.
render :layout => false
means that you want to render 'toggle' view without layout.
If you don't want render anything at all, you should use :nothing => true
option
def toggle
@task = Task.find(params[:id])
@task.toggle! :status
# if it used only by AJAX call, you don't rly need for 'respond_to'
render :nothing => true
end
EDIT: In Rails4/5 you can use head :ok
instead of render nothing: true
, it's more preferable way to do this, but result is the same.