How to serve a static JSON file in rails? - ruby-on-rails

I have a file on my server that's outside of my app directory. It's a text file that holds a json object, /path/to/data.json.
What's the simplest way to serve this file in Rails, e.g. to return it in response to a GET request?
Here's what I've tried so far, inspired by this answer and others. (This may be way off-base -- I'm new to rails.)
added this line to routes.rb
resources :data
Wrote the following data_controller.rb
class DataController < ApplicationController
#data = File.read("/path/to/data.json")
def index
render :json => #data
end
end
This doesn't work. When I direct my browser to http://myserver.com/data.json I just see "null" instead of the data.json file.
Any idea what I'm doing wrong?

I think this is a scope issue; your outer #data is not the same as the #data in a method. That is, you can't use instance variables as expected outside of methods because there is no instance yet.
It should work if you use a class variable, eg
##data = File.read("/path/to/data.json")
then
render :json => ##data

Put it in public/assets/javascripts. Or app/assets/javascripts. The server may even return the correct content-type.

put data.json file into your project directory ( for example public/data.json)
#data = File.read("#{Rails.root}/public/data.json")
At last but not least render :json => #data

You can also do it in one line, e.g.
render :file => '/path/to/data.json',
:content_type => 'application/json',
:layout => false

Related

Rails create file and render

In rails, is there a way (in a controller) to:
create a file
render a view or template to that file
redirect_to or render another view
I've tried all kinds of constructions, but keep getting the same error: Render and/or redirect were called multiple times in this action. Please note that you may only call render OR redirect, and at most once per action.
Otherwise; is it possible to render a template or view to a file without displaying that template/view?
thnx!
code:
def get_report
# part 1: create and render file for use with phantomjs
File.new('./vendor/assets/javascripts/graph_disk1.json','w') {|f| f.write(render "reports/disk", :layout => false)}
system `phantomjs ./vendor/assets/javascripts/highcharts-convert.js -infile ./vendor/assets/javascripts/graph_disk1.json -outfile ./app/assets/images/chart01.png -options ./vendor/assets/javascripts/resources.json`
# part 2: create odf-report and use image created bij phantomjs/highcharts-convert
report = ODFReport::Report.new("#{Rails.root}/app/report_templates/PSC2_KalScanV0.odt") do |r|
r.add_image :graphd1, "#{Rails.root}/app/assets/images/chart01.png"
send_data report.generate, type: 'application/vnd.oasis.opendocument.text',
disposition: 'attachment',
filename: 'report.odt'
end
end
the 2 parts work each, but not when called liked this (in 1 action/controller).
The solution is always easy once you've found it:
Instead of: f.write(render "reports/disk", :layout => false),
Use: f.write(render_to_string "reports/disk", :layout => false)
and voila, no more error
it seems you tried to create custom routes with render different file other than rails way, let me give you sample case, for example you have client controller but then you want to create custom method and routes other than 7 standard rails way
rails generate controller clients
inside routes.rb
resources :clients do
collection {
get :check_data # this to get data
post :import_data # this to post data
}
}
# prease remove all other routes for client controller that usually generated with get
inside app/controllers/client_controller.rb create two method for route above
def check_data
...
# the default view file is /views/clients/check_data.html.erb
# but you may also type like this below to render other file
# please note the first thing you must mention controllers name then the file name
render "clients/noname.html.erb"
end
def import_data
...
#
# here after client saved, it goes to other path instead of default
if #client.save
redirect_to courses_path
end
end

Rails download http response/displayed site

Instead of displaying the xml file rendered by the index.api.rsb file in my browser, i want to download it. To me this sounds very simple, but I cant find a solution.
I tried the following in the controller-method:
def split
if params[:export] == "yes"
send_file *here comes the path to xml view*, :filename => "filename", :type => :xml
end
respond_to ...
end
The result is a MissingFile exception...
Thanks in advance
Note that :disposition for send_file defaults to 'attachment', so that shouldn't be a problem.
If you have a MissingFile exception, that means the path is incorrect. send_file expects the path to an actual file, not a view that needs to be rendered.
For your case, render_to_string might be what you need. Refer to this related question. It renders the view and returns a string instead of setting the response body.
def split
if params[:export] == "yes"
send_data(render_to_string path_to_view, filename: "object.xml", type: :xml)
end
end
To force it to download it, add :disposition => attachment to your send_file method.
Source: Force a link to download an MP3 rather than play it?

Rails 3 / ActiveAdmin controller_action won't return a plain JSON array

Contrived example:
ActiveAdmin.register Something do
# stuff
controller_action :sad_trombone, :method => :get do
render :json => ["wah", "wah", "wahhh"]
end
end
I hit /admin/somethings/sad_trombone. The JSON response I get looks like this:
{ somethings: ["wah", "wah", "wahhh"] }
While I appreciate the convenient, automagical somethings namespace, I just need my sad_trombone controller to return a plain array, like so:
["wah", "wah", "wahhh"]
How do I do that?
If useful, I'm using:
activeadmin (0.6.0)
rails (3.2.13)
(This is just a simplified example for illustrative purposes.)
Found a solution:
render :json => ["wah", "wah", "wahhh"], :root => false
The :root => false option instructs Rails not to include a root JSON object -- in other words, just the plain data structure you want to return in the response.
In case it's helpful to posterity:
There are (at least) two other, but much more broad ways of accomplishing this:
ActiveRecord.Base.include_root_in_json = false
And:
my_model.to_json(:root => false)

How do you output JSON from Ruby on Rails?

I'm looking to have a model that gets created / updated via AJAX. How do you do this in Ruby on Rails?
Also, more specifically: how do you output JSON in RoR?
def create
response = {:success => false}
#source = Source.new(params[:source])
if #source.save
response.success = true
end
render :json => response.to_json
end
All you need to do is call render :json with an object, like so:
render :json => my_object
For most objects, this will just work. If it's an ActiveRecord object, make sure to look at as_json to see how that works. For your case illustrated above, your hash will be transformed to json and returned.
However, you do have an error: you cant access the success key via response.success -- you should instead do response[:success]
jimothy's solution is really good butI believe it isn't scalable in the long term. Rails is meant to be a model, view, and controller framework. Right now JSON is cheated out of a view in default rails. However there's a great project called RABL which allows JSON view. I've written up some arguments for why I think it's a good option and how to get up and running with it quickly. See if this is useful for you: http://blog.dcxn.com/2011/06/22/rails-json-templates-through-rabl/
#source = Source.new(params[:source])
respond_to do | f |
f.html {
# do stuff to populate your html view
# maybe nothing at all because #source is set
}
f.any(:xml, :json) {
render request.format.to_sym => #source
}
end

Saving XML files with Rails

im working on a Rails project that should create XMl files, or to be more specific
use existing XMl templates and put content from the database in it.
So i dont need to create the xml structure, basically just rendering a template with content.
What would be the smartest way to do that?
So far i have a file.xml.erb in my layout folder
and i have a custom route "/renderXML" that does
def renderXML
#reading_question = ReadingQuestion.find(params[:id])
render :file => 'layouts/question.xml'
end
This works, but i also want to save the file, not only show it (actually viewing it is not really needed).
For saving i found this
File.open('fixed.xml','w'){|f| f.write builder.to_xml}
How do i access the rendered file and save it with some method like above?
Perhaps something like:
s = render_to_string :file => 'layouts/question.xml'
File.open('fixed.xml','w'){|f| f.write s}
render :text => s
Another approach :
send_data fixed, :type => 'text/xml; charset=UTF-8;', :disposition =>
"attachment; filename=fixed.xml"

Resources