Rails Ajax approach without database - ruby-on-rails

The different Rails 3/Ajax solutions I have come across show examples that retrieve data from a database.
I would like to make an Ajax call and have the server return data that does not come from a database. The data actually comes from REST aware pages on the web.
Any suggestions or examples?

See this example:
# Use the class methods to get down to business quickly
response = HTTParty.get('http://twitter.com/statuses/public_timeline.json')
puts response.body, response.code, response.message, response.headers.inspect
With HTTParty gem.
You will return results as usual with Rails, for example, you could call in your controller:
render json: response.body
If you want it AJAX you can call this controller I mention with:
$.get('my_rails_route');
Check your requirements, you could simply do:
$.get('http://twitter.com/statuses/public_timeline.json');
Without passing by Rails server.

Related

How to connect 2 rails 5 apps together API (rails) and front-end (rails as well)

As i mentioned on the question title, I want to know the best approach to get this to work and i'll need and example ( very simple one as the follow: )
Let's say i have an API which has 1 controller and 1 action for example simplicity
root 'main#index'
and inside the index action i have
def index
#date = Data.today
end
Then i have another rails app which will work for front-end rendering
How can i pass this #date as JSON from the API to the other app to render it ?
Should i have same controller on the other app ?
How can i connect and send http request and receive response ?
Thanks in advance
For such a simple example, you can do something as simple as:
def index
#date = Date.today
respond_to do |format|
format.json #date
end
end
However, you're most likely going to want to deal with more complicated JSON responses, so before long you'll probably want to use something like the Jbuilder gem or ActiveModel Serializers (my preferred approach).
On the other end, your front-end will need to make an HTTP GET request. Lots of ways (and gems) to do this, but one common approach is just to use the built in Net::HTTP class.
require 'net/http'
url = URI.parse('http://backend.dev/main/index')
request = Net::HTTP::Get.new(url.to_s)
response = Net::HTTP.start(url.host, url.port) do |http|
http.request(request)
end
raise response.body.inspect
In your situation, a better approach might be to use the Active Resource gem. This gem allows you to create models that are backed by a REST API rather than a database. For example, if your API app provides basic Create-Read-Update-Destroy actions for a particular model (let's call it Widget) at the following URLs:
GET http://backend.dev/widget # listing of widgets
GET http://backend.dev/widget/1 # Read for widget id: 1
POST http://backend.dev/widget # Create new widget
UPDATE http://backend.dev/widget/1 # Update widget id: 1
DELETE http://backend.dev/widget/1 # Destroy widget id: 1
then in your front-end app you could declare an Active Resource like this:
class Widget < ActiveResource::Base
self.site = "http://backend.dev"
end
which will auto-magically access all of those methods in your API, and behave much like a regular Active Record model. That way, you basically design your front-end app like a "normal" rails app, but using ActiveResource-based models in place of ActiveRecord.
I would note, however, that a more common thing to do these days would be to build your API in Rails, and build your front-end with client-side Javascript, using something like JQuery or Angular to make requests from the API. I'm not sure what you're gaining by splitting API and front-end, where both of them are Rails apps - unless you've got a compelling reason, I'd just build one Rails app that handles both API and front-end, or build a Rails API + Angular (or similar) front-end.

Where does FactoryGirl save db entries in a Rails API app?

I'm fairly new to rails and I'm currently creating my first API only rails app.
What I'm struggling to get my head around is where exactly are entries being stored in the test environment? In a full rails app FactoryGirl would store entries in the _test database and passed to the controller - tested via something like RSpec.
I understand that in a rails API app you're foregoing the use of databases and instead aiming to store data in JSON format on a server - but in the case where I'm writing request specs, where is the information being stored/retrieved from? There is no server (locally or remotely) to hold the data!?
Apologies for my newbie question!
JSON is just the format you use to make the communication from the client and the server, and backward, happen. But data are stored in a database as well. This is a spec I wrote in a rails api project to save a category (it's a request spec).
context 'everything is ok' do
it 'gets a successfull response' do
params = { category: category }.to_json
post "/categories", headers: headers.merge("X-Api-Key" => partner.token), params: params
json = JSON.parse(response.body)
expect(json['success']).to be true
expect(json['category']['name']).to eq 'Programming Languages'
end
end
Just to give you an idea, I'm not pro at testing, I'm learning as well.
and instead aiming to store data in JSON format on a server
Nope. That would be silly. Rails API app is a regular rails app (with a database and whatnot). Only it does waaaay less html view rendering (ERB and such). That's the main difference.

Create a generic template for JSON from a rails application

I'm writing a rails application with an AngularJS front-end, this is part of a tutorial series I'm writing on connecting rails and angularjs. This means my rails application communicates with the browser exclusively in JSON.
In the angularjs $http documentation it describes a potential json security vulnerability where the json request can be embedded into a script tag, plus some tricky use of jsonp, to allow something akin to a cross-site scripting attack. I've found a few other pages, one in particular I thought described this well, and dates from 2008, so this isn't a new issue.
Apparently this isn't a vulnerability in standard rails json rendering, as rails by default provides back an object containing an array. But when working with angularjs we appear to set root: false (although I have to confess I can't find where I did that, but it's definitely not giving the root node).
Anyway, the bottom line is that the angular documentation recommends prefixing any json response with )]}', so:
['one','two']
Becomes
)]}',
['one','two']
Angular then automatically strips that off again.
I'm looking for a way to do this elegantly. I've seen a lot of questions and answers on stackoverflow about this, but most of those either relate to much earlier versions of rails before JSON handling was more thoroughly embedded, or seem to require me to create a lot of boilerplate code. I'm looking for a method that I can apply to the application controller, or as a helper method, that will work everywhere.
The controller that I'm currently using looks as follows:
class ClubsController < ApplicationController
respond_to :json
# GET /clubs.json
def index
#clubs = Club.all
render json: #clubs
end
end
This doesn't call any templates - the render action skips the templating engine. I can get this working by changing the render line instead to:
respond_with json: #clubs
And creating a template file views/clubs/index.json.erb that contains
)]}',
<%= raw(#clubs.to_json) %>
But I'd then have to create a template for every action on every controller, which feels like boilerplate. I'd like instead to be able to change views/layouts/application.json.erb to have something like:
)]}',
<%= yield %>
But that doesn't work because we only get templating if we call respond_with. And if we call respond_with, we have no way to put the #clubs into the response - so we end up with:
)]}',
As the entirety of the response.
An alternative would perhaps be to override the as_json method to prepend what I want, but that seems a bit like a sledgehammer. Ideally there would be a place I could introduce a helper method, something like:
render prepend_vulnerability_protection(json: #clubs)
So, after all that, two questions:
Is this even a real problem, or does Rails already have some other protection that means I don't need to worry about this at all
Is there a way to do this centrally, or do I need to bite the bullet and create all the boilerplate templates? I can modify the scaffold generators to do it, so it's not the end of the world, but it does seem like a lot of boilerplate code
So, no responses as yet. I'm going to write down what I find from my research, and my current answer.
Firstly, I think this is a genuine vulnerability in rails. Unfortunately the rails and JSON/JSONP area has had some other recent vulnerabilities relating to the JSON parser at the Rails end. That has really drowned out any google search relating to this specific XSS issue.
There are a couple of approaches to resolving this:
Have your application only respond to put/post/delete requests. That's not really an option when integrating to Angular - well, it is, but it means overriding a bunch of standard behaviour
Insert something at the front of your returned JSON - this can be the root node (default rails behaviour in rails 3, no longer in 3.1), a closure like )]};, or a loop like while (1);. Angular expects and can deal with )]}',
I've looked at using a json template in my rails app. You can do this with one of many gems, the one I like the look of is JBuilder (railscast 320), but RABL is perhaps more powerful (railscast 322).
This does mean a template for each of the actions on each of the controllers. However, I've also just completed working out how to have rails scaffold those for me automatically, so it's not as scary as it was when I first asked the question, and I can see some other reasons that I might want more control over the json that is returned from my application.
Having said that, I couldn't immediately see a way to get JBuilder to prepend an arbitrary string - it seems to only want to prepare valid JSON (and this I think is not valid JSON). RABL looks like it can do it, but it is a bit more complex. It can definitely be done through just using ERB, but I feel kinda wrong in doing that.
The other alternative I've identified is a helper method in application_controller.rb, which I then call in each of my controller methods. This is reasonably elegant, and I can quite easily change my template to do it. So I'm going with this for now:
class ApplicationController < ActionController::Base
def render_with_protection(json_content, parameters = {})
render parameters.merge(content_type: 'application/json', text: ")]}',\n" + json_content)
end
end
class ClubsController < ApplicationController
respond_to :json
# GET /clubs.json
def index
#clubs = Club.all
render_with_protection #clubs.to_json
end
# GET /clubs/1.json
def show
#club = Club.find(params[:id])
render_with_protection #club.to_json
end
# POST /clubs.json
def create
#club = Club.new(params[:club])
if #club.save
render_with_protection #club.to_json, {status: :created, location: #club}
else
render_with_protection #club.errors.to_json, {status: :unprocessable_entity}
end
end
end
Note that you should be also including CSRF protection in your application controller - so see this as additive to the security precautions you were already taking, not a replacement.

Is there any gem to send request to some service in xml format

I want to send request to some third party service in xml and also expecting response in xml. I'm searching for some gem or any idea how to do this.
Thing which is in my mind is to
make some partail _example.xml.builder
onclick from my view to some button send ajax request to controller action and use render_to_string to render that xml doc and then
Save it in some variable
and then call to that service method in same action
But it is not proper thing as I expect there should be some thing more efficient than my suggested thing
RoR doesn't natively use XML so some degree of conversion is required.
Having said that, XML generation is very simple in RoR applications. There are several ways of doing this, my favourite being constructing the required data as a Hash (which is native to Ruby) then the_hash.to_xml.
The XML conversion can also be defined in a model Class if you wish a consistent result:
class Example < ActiveRecord::Base
# ensure that only column1, column2, etc are output as XML
def to_xml(options = {})
super( options.merge( select(:column1, :column2, etc) ) )
end
end
Then in your controller:
poster = Example.find(123)
request = Net::HTTP.new('www.example.com', 80)
request.post('/path', poster.to_xml)
Hopefully the above demonstrates a simple example of posting XML data to a remote host. As you mentioned, a more complicated XML can be constructed using xml.builder
HTH and good luck.

Ruby on rails web services with POST request

I've just started learning Ruby on rails and I am wondering how to do something that I know how to easily do in PHP.
I want to create some basic web services that can be called with POST parameters and send a JSON as a response. I don't know at all how to start with that using Ruby on rails.
I am sure there are some best practice to do that kind of things, so if you guys could advise me anything, it would be great!
Regards,
To get the POST parameters, you just look into the params hash in your controller, which will have any and all parameters for the request, whether they're coming as POST params, GET params, or as part of the route (e.g. /users/:id/new => params[:id] in the controller)
To return json from the request, you'd just make a render call like this:
render :json => #model
Beyond that, your question is a bit broad for the scope of an answer on SO. I recommend reading Agile Web Development with Rails as a starting point to learn Rails development.
Sounds like a good fit for Sinatra. Check out http://www.sinatrarb.com/
The great thing about rails is that it is based on the principal of REST.
Whenever you create a RESTful resource, you are in fact creating a web service at the same time.
For example. Say you create a resource using a scaffold generator.
rails g scaffold Feed title:string content:string
This will not only create all the view logic in HTML, but also in xml.
Further to your first comment:
If you look in the controller, within the respond_to block you can specify the return type. So you want to hit the xml version of new and return the json version of create.
To render your treated parameters to json, put them in a hash:
js = {:my => {:json => 'hash'}}
render :json => js

Resources