How can I toggle a boolean field in Rails 3 using AJAX? - ruby-on-rails-3

I have a column in a table called Complete that is a boolean.
How can I (using the Rails 3 / JQuery way) provide a link that will toggle that via AJAX?
Historically, I've simply created my own jquery file, grabbed the click event, and done it by hand. But it really seems like I'm missing something by not doing it the "rails" way. If that makes sense.
I guess I still don't understand how the responds_to JS works, JS with ERB, etc.
Is there a good, up-to-date tutorial on how to do this?
Thanks.

see this post,
Rails 3, Custom Actions, and HTML request methods
and use UJS on top of it.
so you have a fallback, if javascript is disabled
a possible method in the controller looks like that:
# GET /surveys/1/close
def close
#survey.close!
flash[:success] = "Survey successfully closed!"
respond_to do |format|
format.html { redirect_to(surveys_url) }
format.xml { head :ok }
format.js { render :partial => 'list_item', :locals => { :survey => #survey } }
end
end
you could also use a state machine to change the state of your object.

Related

Rails + best_in_place + Twitter Bootstrap

I have really annoying issue with best in place and Twitter bootstrap. I have spent with that a lot of time. I have gone through several pages - best_in_place github page and Issues. So I thought, that I fixed it but not and I don't know where the mistake is.
When I'm using best_in_place for the first edit, it works, save the value and the input is changed back to the "normal" view with new value. But when I want to do the same action( edit it) second time, its not working. I have to reload the page and then I can edit it again only once. My code is bellow:
AccountsController.rb
def update
#account = current_user.account
respond_to do |format|
if #account.update_attributes(params[:account])
format.json { respond_with_bip(#account) }
else
format.json { respond_with_bip(#account) }
end
end
end
View
<%= best_in_place current_user.account, :introduction, :type=> :input,
:nil => "Click me to add your introduction!",
:html_attrs => {:'data-provide' => "typeahead" } %>
account.js.coffee
jQuery ->
$('.best_in_place').best_in_place()
I have already seen this pages and haven't found the answer:
SO Thread, ExampleApp, Best_in_place Issue
Please, could someone help me? I know that is maybe caused by Twitter Bootstrap, but I don't know how to fix it:(
OK, I have found the solution for that.
The "issue" is in this line:
format.json { respond_with_bip(#account) }
I replaced it with:
format.json { render json: #account}
And its working now. But it was just luck. Do anyone know what is the main difference here? Why one is working and the second no? What exatly the respond_with_bip does?

How to construct form_tag URL that PUTs to an external API

I'm using the Shopify API http://api.shopify.com/
And the Shopify Gem: https://github.com/Shopify/shopify_api that does most of the heavy lifting- just can't quite figure out how to make it work.
To update an #variant object I need to PUT here: PUT /admin/variants/#{id}.json
In config/routes.rb I made default resource routes with resources :variants and now I'm trying to make a form that updates a variant resource but can't configure the form to have the proper action.
Basically I'm constructing form_tag with a text field input that takes an integer and updates variant.inventory_quantity
Rake Routes give me this:
rake routes:
variants GET /variants(.:format) variants#index
POST /variants(.:format) variants#create
new_variant GET /variants/new(.:format) variants#new
edit_variant GET /variants/:id/edit(.:format) variants#edit
variant GET /variants/:id(.:format) variants#show
PUT /variants/:id(.:format) variants#update
DELETE /variants/:id(.:format) variants#destroy
You need to declare variants resource under admin namespace like this:
config/routes.rb
namespace :admin do
resources :variants
end
EDIT:
You don't have to do anything special for Rails to accept JSON. Rails will convert the JSON you passed in PUT into params and make it available to update method.
Here is the standard implementation of 'update' method:
app/controllers/admin/variants_controller.rb
def update
#variant = Variant.find(params[:id])
respond_to do |format|
if #variant.update_attributes(params[:variant])
format.html { redirect_to(#variant,
:notice => 'Variant was successfully updated.') }
format.json { head :no_content }
else
format.html { render :action => "edit" }
format.json { render :json => #variant.errors,
:status => :unprocessable_entity }
end
end
end
Refer to Rails guide and layout and rendering for details.

After deleting a record in Rails 3, the refreshed view isn't updated

I'm dealing with a basic one to many relation where I'm deleting a record on the many side. The models are "places" and "search_terms" where places has_many search_terms. When I create a new record, the view is updated and the new search_term appended to the list. However, when I delete a search_term record the view is not refreshed even though it deletes the record and runs the "show" method for Place.
I'm quite new to rails 3 so can't really figure out whats going on here...
Cheers,
Gearoid.
Edit: the search_terms controller destroy method:
def destroy
#search_term = SearchTerm.find(params[:id])
#search_term.destroy
#place = Place.find(params[:place_id])
redirect_to place_path(#place)
end
The places controller show method:
def show
#place = Place.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => #place }
end
end
I might be misunderstanding you, could you post your controller's code?
Is this happening over ajax? If not, can you redirect to the Show instead of just re-rendering it? That's probably a preferred experience for the user anyway.
UPDATE
Ok, if this is going over ajax, then the problem is simple. Your destroy action is only expecting a normal browser event and doing a redirect_to call. The ajax call doesn't know how to handle it and just sits there. You can probably see the redirect code in something like Firebug.
I'm not super familiar with jquery-rails (I prefer to write all my js myself because I'm anal). You can have the destroy action return a js format like so:
def destroy
#search_term = SearchTerm.find(params[:id])
#search_term.destroy
#place = Place.find(params[:place_id])
respond_to do |format|
format.html { redirect_to place_path(#place) }
format.js { render :nothing => true }
end
end
That will give the ajax caller the ok signal that it has done its thing. Your javascript will still have to intelligently handle this response though, like remove the element from the DOM.

problem with RESTful forms in Rails 3

okay, so basically, I have a normal form for my model:
= form_for #operator do |f|
blah blah blah
In my operators controller, i have this:
def new
#operator = Operator.new
#operator.build_user
respond_to do |format|
format.html {}
end
end
def create
#user = User.create(params[:operator].delete(:user))
#user.update_attributes(:login => #user.email)
#operator = Operator.new(params[:operator].merge(:user => #user))
respond_to do |format|
if #operator.save
format.html {redirect_to new_operator_aircraft_path(#operator)}
else
format.html { render :action => "new", :error => #operator.errors }
end
end
end
very basic stuff. I have some validates_presence_of stuff in my model so naturally when I submit my form, it should show me that I have errors(and keep the fields I have filled up)
Right so far? yeah. The problem is, it seems I am posting to /operators and that's what renders. I seem to have forgotten about what happens in Rails2.3+ but shouldn't I be redirected to /operators/new again? or was that the intended behavior all along?
Here's what I think you are asking:
After I submit a form with errors, why does the URL
read "/operators" rather than
"/operators/new".
Thanks to resourceful routing, when submitting a form via POST to "/operators" the create action is called on the OperatorsController. If you encounter errors when saving your operator, you've instructed the controller to render the new action within the same request.
render :action => "new", :error => #operator.errors
This means a redirect is not occurring and therefore the URL remains "/operators".
If a redirect were to occur, you would lose all the state information of the #operator object in the current request, including the errors you encountered as well as the form values you just submitted.
In other words, working as intended.

jquery-ujs ajax events are not handled

I'm trying to implement ajaxy signup with rails 3. I'm using jquery-ujs and remote form. I access the signup form with $.get request, and it is displayed correctly. This signup form is remote:
form_for #user, :remote => true, :html => {"data-type" => "html"} do |f|
In my application.js, if the ajax request for getting the form is successful, I'm trying to bind handler for ajax events from unobtrusive javascript:
var load_remote_form = function(evt) {
var href = $(this).attr('href');
// load form template
$.get(href, {}, function(data) {
$('body').append(data);
$('form[data-remote]').bind("ajax:beforeSend", function(e) {
console.log("Caught beforeSend!");
});
});
evt.preventDefault();
};
$(document).ready(function() {
$('a#signup').click(load_remote_form);
});
Chrome's development tools show that the event "ajax:beforeSend" is binded, but it is never handled (I have nothing in the javascript console when I send the form, though in rails log I see that the request is processed correctly and the response is send). I can bind other events to the same selector (form[data-remote]), like click, and they are handled correctly.
Ajax events binded through .live are not handled as well. But if the form is rendered as part of the layout (i.e. it is on stand-alone page like http://localhost:3000/signup/), binded "ajax:beforeSend" is handled correctly.
My controller (just for a case, it may be badly written, but I'm pretty sure it works):
class UsersController < ApplicationController
layout :layout_for_type
def new
#user = User.new
end
def create
#user = User.new(params[:user])
if #user.save
session[:user_id] = #user.id
flash[:notice] = "You have successfully registered."
redirect_to root_url
else
if request.xhr?
render :action => 'new', :status => :unprocessable_entry, :layout => false
else
render :action => 'new'
end
end
end
def layout_for_type
request.xhr? ? nil : "application"
end
end
What am I doing wrong? May be there is a better approach for implementing such "double-ajaxed" forms?
Silly me. I've completely overlooked another potential source of problems. I had
javascript_include_tag :all
in my application layout, and that caused including both jquery.js and jquery.min.js into my page. It turned out to be the cause of that strange behavior. Removing jquery.min.js did the trick. Hope that might be useful for someone someday.