rails refresh page on json response - json

I am trying to upload a file using dropzone. When the file is uploaded, I want to redirect the page to root url. When I upload the file, the request is sent and the response is in json format. I have in my controller:
respond_to do |format|
format.json{ render :json => { :location => root_url, :flash => {:success => "The file was uploaded successfully"} }}
end
Can please anyone help me with what is wrong with my respond_to block?

This json response will not in itself redirect, as it responds with json to (presumably) an ajax request. When the response comes back, the client will need to do something with that response, such as set window.location to the :location attribute.
ie in the success callback of the dropzone request

Related

Sinatra Content Type both json and form

I have been looking all over for how to properly check respond to a application/json type as well as a submitted form. I finally got it working on my own with the following code. Can someone explain why it works? Or offer advice on a better solution to achieve the same thing?
post '/login', provides: :json do
p = params
if request.content_type == 'application/json'
params = JSON.parse(request.body.read, :symbolize_names => true)
else
params = p
end
requires(params, :email, :password)
if #user = User.find_by_email(params[:email])
if #user.authenticate(params[:password])
log_user_in(#user)
rabl :login, object: #user
else
error 404, {error: "incorrect credentials"}.to_json
end
else
error 404, {error: "user not found"}.to_json
end
end
JSON requests are submitted in the body of the html request so this works but overriding the params hash is not advisable if using RESTful routes.
Hey Curtis.
Just use ::Rack::JSONBodyParser from rack-contrib:
A Rack middleware that makes JSON-encoded request bodies available in
the request.params hash. By default it parses POST, PATCH, and PUT
requests whose media type is application/json. You can
configure it to match any verb or media type via the :verbs
and :media options.
Examples:
Parse POST and GET requests only
use Rack::JSONBodyParser, verbs: ['POST', 'GET']
Parse POST|PATCH|PUT requests whose Content-Type matches 'json'
use Rack::JSONBodyParser, media: /json/
Parse POST requests whose Content-Type is 'application/json' or 'application/vnd+json'
use Rack::JSONBodyParser, verbs: ['POST'], media: ['application/json', 'application/vnd.api+json']

Send an http response to another site

Noob
How should I send a single string variable to another site from my rails app? ie the outside service sends a get request to my controller/route and then the controller must respond with the string (and I assume a response code). The string is intended to be added to their html code.
In my controller should I
render :text => "string"
or
respond_with("string) #as xml or json
or something completely different?
Just try the following code. Here your application gives the text and json as per the request.
respond_to do |format|
format.json do
render :json => 'string'
end
format.html do
render :text => 'string'
end
end

Rails routing - how to add .html extension to the routing rule?

I have this rule:
match '*urlnames' => 'home#searching_names'
The URL address looks like website.com/john.html.
The problem is, that in the log I see
Parameters: {"urlnames"=>"john"}
without the .html extension. Text extension is important, I would need to test it in the controller.
I tried to add to the routing rule this part:
match '*urlnames' => 'home#searching_names', :defaults => { :format => "html" }
But still the same, in the log is
Parameters: {"urlnames"=>"john"}
How can I catch the extension in the controller?
You have access to the requested format via request.parameters[:format] or (as a MIME type) via request.format.
However, you can also use a respond_to block:
def show
file = params[:urlnames]
respond_to do |format|
format.html { ... }
format.txt { ... }
end
end
where ... is code to render some text, or send some data or a file.
If you're just trying to show some static files, just place them in the public dir, and bypass Rails entirely.

getting csrf tokens for json post requests to a rails app

I have been playing around with using rest-client to access a rails app I have written. I've written a quick script to log in and make a post request. Everything is working but I did have to work round the fact that no authenticity_token is served if you make a request for a form in json. I had to make a regular html request in other get the authenticity_token and then included this in the json I submitted as part of my post request. Basically I have a quick an dirty script like the one below
private_resource = RestClient::Resource.new( 'https://mysite.com')
params = {:user => {:email => 'user#mysite.com', :password => 'please'}}
#log in
login_response = private_resource['users/sign_in'].post(params, :content_type => :json, :accept => :json)
#get cookie
cookie = login_response.cookies
#get json
json_response = private_resource['products/new'].get(:content_type => :json, :accept => :json, :cookies => cookie)
#another request that returns html form with authenticity token
response_with_token = private_resource['products/new'].get( :cookies => cookie)
#extract token
token = Nokogiri::XML(response_with_token).css('input[name=authenticity_token]').first.attr('value')
#update cookie
cookie = response_with_token.cookies
#populate form and insert token
form = JSON.parse(json_response)
form['name'] = "my product"
form['authenticity_token'] = token
#submit the request
private_resource['products'].post(form.to_json, {:cookies => cookie, :content_type => :json, :accept => :json})
There is the option to turn off CSRF protection for json requests but I would rather not do that. I could go the mechanize route or something similar and then I wouldn't worry about json requests with CSRF but I just wanted to play around with doing this stuff with rest-client
I guess I'm just curious to know if there is a reason why no authenticity_token is served for json requests and I'm also wondering if there is a better way of solving the token problem than the pretty hacky approach I've taken here
Put the below code into your application controller :
def verified_request?
if request.content_type == "application/json"
true
else
super()
end
end
And call this method using before_filter .
For more details check :
http://blog.technopathllc.com/2011/09/rails-31-csrf-token-authenticity-for.html
And check this issue in rails : https://github.com/rails/rails/issues/3041
In your app/views/products/new.json.jbuilder, add this:
json.authenticity_token form_authenticity_token
This will insert a key "authenticity_token" with value being the token, so in your json_response you get the token as well. Idea from this answer.

respond_with redirecting when format=json

I'm encountering a strange behavior in my controllers. They seem to occasionally want to redirect instead of render a json response.
respond_to :json, :html, :js
def create
#favorite = current_user.favorites.build(:location_id=>params[:location_id])
if #favorite.save
respond_with(#favorite)
else
respond_with(#favorite.errors)
end
end
I think it works most of the time but today I was notified of this error:
NoMethodError: undefined method `favorite_url' for #<FavoritesController:0x00000006171dc0>
The params hash was logged as:
{"format"=>"json",
"action"=>"create",
"user_id"=>"56",
"auth_token"=>"iGSty8CMIaWsbShYZEtw",
"location_id"=>"47943",
"controller"=>"favorites"}
Especially strange since it seems to work most of the time... I have changed a few of my other controllers to use the old format.json { render :json => #object } syntax but I'd like to avoid that if possible.
How could this be?
On paths that are not GETs, respond_with tries to redirect to the url for whatever it is given. You can override this with a custom Responder