Inspect RoR json API - ruby-on-rails

Is any way (I mean RoR code) to enumerate
exising API endpoints
input data with data types
output data with data types
something else
Let suppose we use ruby on rails and our api is based on models and its types.
( Something like with schema here )
What is possible and how?
What is not possible and why?

This is generally not possible.
The controllers (and models) in a Rails app define on various layers what data to accept. This is generally not defined in a static format but through a layered validation process (e.g. on the controller with strong_parameters and the models with their validations.
Since those validations can define arbitrarily complex business rules using Ruby code, usually, you can thus only check if a given data structure is accepted by trying to pass it to the app and checking if it accepts it without any errors.
With that being said, there are gems which allow you to define "abstract" API schemas which might be consumed by external clients and used to validate data in your app. Examples here are trailblazer, dry-validation, json-schema and others. Note that these approaches usually require to follow the architectural requirements of these gems which might heavily affect the way you design your application.

Related

How to properly version Ruby on Rails APIs?

When talking about Ruby on Rails API versioning, it's common to create a division in the controller level. They create new routes with new controllers in different modules, such as API::V2::ProductsController and so on.
The problem is: not all the code is in the controllers. Even a simple Ruby on Rails application has its code shared between models, views (which in this case would be the serializers) and controllers. Not to mention jobs, mailers and application specific libraries (lib/ directory) code.
Even if you version the controller with new controllers with different routes, the model would be the same for every version, and so would be the views and the database schema itself.
I know ActiveModelSerializer, one of the most used serializing gems, does implement versioning, but still, Rails models don't support versioning by default.
Is there a way to really version a Ruby on Rails API?
I would say that your view layer: your serializers or .rabl or .jbuilder files should contain as much presentation logic as possible (ideally all!). Thus: how this data is displayed to the user: a pretty formatted string, a JSON document with a certain structure, a JSON document with a slightly different structure.
If you have a User model, and you want to format the date a user joined the site, don't implement a User#dateUserJoinedISOStr method, but instead in the serializer get the date field and do the transformation to the proper iso string there.
Then you can switch on the API version requested, or use a completely different serializer if the changes between the two API versions are just too different.
Theoretically maybe you even think of the two api versions as different representations of the same resource, and use / abuse Rails content type format tools to pick the right content template.
This of course gets harder if you have a site that returns HTML as well as JSON (or, to put it a better way, "HTML representations in addition to JSON representations"). In that case I'd either use some clever route magic such that the version comes through the params OR buck convention a little bit and don't put a version number in your URL path (instead use a header!). Regardless, if your routes always go to the same place, then either have some if statements in the controller (to select the correct version serializer) OR a bunch of if statements in the serializer ("display that now, or not?").

Correct rails place for no-db data fetching code

I'm looking for the "rails" design pattern for code that fetches data from other websites.
I have a rails controller in my app that fetches data not from the database, but from external API's or scraped from the web.
Where's the "rails" place to put this code.
For quick implementation, I just stuck it in a model, but the model doesn't interact with the database - or support standard model functionality - so that feels wrong, but my understanding of rails and ruby isn't yet solid enough to know where it should go.
The way the code works roughly is
controller calls model.fetchData args
the model uses HTTParty or similar to make the call
processes data
passes it back to the controller
Any advice?
Broadly-speaking I think there are two possible ways to do this:
Create a plain ruby class to contain the methods for making requests to the API(s) and processing responses from it(them). You can include the HTTParty module in this class with include HTTParty. The usual place to put this code is in lib/ (make sure that wherever you put it, the path is in autoload_paths).
If you're doing anything really complex, or the API itself is complex, you might want to consider creating a separate gem to handle interaction with the API(s). The term for this type of gem is an "API wrapper" -- if you look around, you'll see there are lots of them out there for popular services (Twitter, LinkedIn, Flickr, etc.)
Notice I haven't mentioned activerecord. If you're not going to be saving anything to the DB, I don't see any need to even create any activerecord models. You can get by with just controllers and views, and then (if needed) pick and choose components from activemodel (validations, internationalization, etc.) to make your ruby API wrapper class feel more like a Rails model. For example, one thing that I've done in an app I'm working on is to apply validations to query strings before actually making requests to an external API, which is a bit like running validations on database queries before querying a DB. See this article by Yehuda Katz for more on how to make plain ruby objects feel like activerecord models.
Hope that helps. I answered another question very similar to this one just yesterday, you might want to have a look at that answer as well: Using rails to consume web services/apis

Rails app with non-HTTP access

Hypothetical question (at the moment!)
Suppose I have a great idea for an application. It acts on data which can be well-represented by tables in a relational database, using interlinked objects which represent those tables. It supports a well-defined API for interacting with (Creating, Reading, Updating, Deleting) those objects, and viewing information about them.
In short, it's a perfect fit for Rails... except it doesn't want to be a web-app. Perhaps it wants a Command Line interface; or an OS-native dialog-based interface; or perhaps it wants to present itself as a resource to other apps. Whatever - it just isn't designed to present itself over HTTP.
These questions suggest it's certainly possible, but both approach the problem from the point of view of adapting an existing web-app to have an additional, non-web, interface.
I'm interested in knowing what the best way to create such an app would be. Would you be best to rails new non_web_app, in order to get the skeleton built "for free", then write some "normal" Ruby code that requires config/environment - but then you have a lot of web-centric cruft that you don't need? Or would it be better to roll up your sleeves and build it from whole cloth, taking just the libraries you need and manually writing any required configuration?
If the latter, what exactly is needed to make a Rails app, but without the web bits?
If you want to access the Rails ORM to develop a CRUD non-web application, just include ActiveRecord in your own Ruby script; you will avoid using a lot of Rails modules you probably don't need (routing, template generator, ...) Here is an example of how to do it.
If you prefer to have the full Rails stack, do not run your Rails web app in an application server (WEBrick, Passenger, Mongrel, ...) to avoid any HTTP exposure, and interact with your application using tasks or the rails console.
I would avoid taking Rails too far off the rails. If I were doing this and felt that the gains of rails w/o the web stuff I'd do the following:
rails new non_web_app
and ignore the webbish cruft and use rails to generate models. In this way you get the tight, comfortable database behavior and can tie various gems in as you want to augment those models. I'd not bother implementing views, of course, and I'd consider implementing controllers in which the various render bits are removed and to use you instantiate an instance of the controller and call the action directly. This means the controller represents your API into your business logic still but the "views" it now "renders" are simply the return of the data output.
Then you could simply strip out the bits you do not need...the public directory, the view structure under app, config/routes.rb, etc. You'll need to test those changes incrementally and make sure that removing some now extraneous bit doesn't throw the Rails world into chaos.
Rails is for Web apps. That means HTTP. Now, you could package a Web app so that it runs on the desktop instead, or you could use ActiveRecord with a desktop application framework like Monkeybars.

Building consumable uri/urls for a model (rails/datamapper/SOA)

Perhaps you can help me think this through to greater detail.
I need to build or make available a uri for a model instance that can be referenced or used by another application which may or may not be a rails application.
e.g.
I create a standard Post with content; I want to build a URL for that post another application can consume or reference by looking at the model in the database (or another less sticky fashion). Datamapper has a URI field, I want to build a canonical uri, store it there and have another application be able to access, announce, manipulate, etc.
Basically, I have several applications that may be in different places, that need to access the same model, to do differing things with the model. I need a way to make that happen clearly without putting them all in one monster application.
I've looked at Pubsubhub, RSS, etc. but haven't found any concrete examples of what I'm trying to do. Do I need to create an common API for the applications, etc?
DataMapper is very flexible about using existing databases.
Many people come to DataMapper because it can create and tear down the database structures without migrations. However, you do not have to work with it in that way.
I have had good success with using a large set of models owned by a central 'housekeeping' app and then declaring a small subset of the same models in separate 'interface' apps.
Some trial and error is required to figure out what works but it can certainly be done. I'd suggest putting your models in modules and including them across apps if possible.
A final point it sounds like you want URIs/URLs to be the primary interface. If that is the case I strongly suggest you look at Sinatra. It is entirely oriented around URLs (and I find Rails routes very obtuse).

Non persistent data in a Rails app

I'm working on an "analytics" page for a rails app. The analytics page does not persist any data of its own (it's very primitive at this point) but does utilize metrics that I'm grabbing from the DB (via the aggregate expressions built into ActiveRecord). Aside from gathering and presenting the metrics the only other requirement I have is to allow the user to provide a date range to filter the data. Up to this point I have been using instance variables and the like to store the metrics information...as the number of metrics grow along with the need to manage the start and end filter dates I begin thinking that I should put this data into its own model. If I do move all of my "data" into a model should I just use a plain object with attr_accessors or is there a more appropriate base class I could use for non-persistent data? I'm familiar enough with a MVC architecture to know that my controller is getting to bloated but no familiar enough with rails to determine how I should organize my data/logic in this case.
Any insight would be greatly appreciated!
It sounds like you could use a Rails non active-record model. There's a good Railscast about that :
http://railscasts.com/episodes/121-non-active-record-model
Hope that helps,
You're on the right track here. Many applications have classes inside app/models that do not inherit from ActiveRecord::Base. Any time you find yourself managing lots of arbitrary variables inside controller actions, it's a good place to consider abstracting that data into a non-persistent model.
This is an area that's not well documented at present, probably because the ActiveRecord stuff is sexier?
I went through the same process, finding my controller actions were becoming uncomfortably large and full of logic as I strove to construct my derived data from ActiveRecord-based models, which in turn started to acquire additional responsibilities that they didn't really want or need.
Once I got the same advice you're getting now the whole thing simplified magnificently.

Resources