I would like to create an application (X) which will analyse model details of a given application.
Ex: Say I have a Rails app called blog, and it has classes like post
#post.rb
#db columns -> title, desc
class Post < ActiveRecord::Base
end
So in my X application , when the path is given of blog, it should read the models of the blog and should come up with its stats (something like Ruby code quality tools).
Example: it should return the columns if the Post class, like List.columns
But my problem is, since my X application is in a different environment than the blog application, how can I load the blog application models and access the functionality as I'm running the blog application from its console itself?
Because lots of Ruby code quality gems are reading the source code as string, but what I want is to use its functionalities as its accessing from the console.
This sounds like the perfect set of requirements for using an API. Just set up your blog controllers to respond to json and then you can make API calls from X to blog to get the information you need.
There are quite a few resources out there for creating an API within your controllers. For Rails 3, I'd recommend Rails 3 In Action by Ryan Bigg and Yehuda Katz: http://manning.com/katz/. There are also numerous blogs, tutorials, etc if you search around.
Related
I am implementing a Wagtail powered blog within a larger (primarily DRF) driven app. I'm attempting to use drf-yasg for my documentation.
Since installing wagtail, the docs are now throwing
'Request' object has no attribute 'wagtailapi_router'
It looks to be related to the introspection that drf-yasg does, and all I can find about excluding views from drf-yasg is done at the code level. Being an installed module obviously I want to avoid that.
Has anyone got these 2 (3) components playing nicely together?
It's been a very long time since you asked this question, but as I found this while looking for an answer myself, I thought I might share what worked for me.
Note that I'm not using drf-yasg, but rather DRF's own schema generator. They do however have a lot in common.
The problem in my case was that the schema generator URL was defined like this:
path(
"schema/",
get_schema_view(title="My API Schema"),
name="openapi-schema",
),
What I needed to add was a patterns= argument that referenced my API specifically, leaving out the other non-API urls (like Wagtail):
path(
"v3/schema/",
get_schema_view(title="My API Schema", patterns=router.urls),
name="openapi-schema",
),
I hope that helps... someone :-D
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
I need a suggestion on how to implement "client-server" web apps in ruby. Any guides and best practices are highly appreciated. I'm interested both in Ruby ways and gems required as it is a desired platform, and in general ways and logic to implement such things.
I'm not an excellent ruby programmer or a skilled system designer with years of expirience sadly so I really need your help as I still hope this thing would shine in the end.
The current look of the application should be like this:
DB + Auth DB <-> API App <-> Other Apps:
DB - a database or set of databases with one DB for group of users (regions).
Auth DB - one more DB with personal users' data and login information, probably single even if main databases would be split between regions.
API App - this thing maintains all the logic around data, access control and translations probably to have one translations base for all the apps.
Other Apps - bunch of different applications, tied with API, this could be data providers that pokes API with some data about some user, and UI of different kinds. All of the apps could not have own storage of user-related info and work with the data only through the API.
API App: looks like the best tool to make it is Sinatra. The questions are:
How to organize API in the clear way? Rails makes nice REST path settings and folders structure for models and controllers. Any tips or gems to improve API building expirience?
How to maintain access? Warden isn't looks like a good option as API clients would be the web apps themselves. So I need some kind of auth token. How could it be done? Some sort of custom OAuth provider? The thing is, I don't like the idea to store and pass session cookies through the API, some sort of access token passed with each request. This also
Other Apps: mainly web-based UIs. The logical selection for this part is Rails. The main question is how to implement client-side auth check. Devise is cool, but is it possible to make it work with token, or is it more suitable tool?
Okay, this is going to be a bit longer:
If you are already familiar with Rails, you can have a look at the Rails API gem. The project strives to remove additional cruft from Rails which is not needed for a JSON-based RESTful API.
This may sound smooth, but it has it's downsides. First and foremost, you have the readd everything that is needed for basic rails functionality, that you may be accustomed to, e.g. respond_to. This can be a bit tricky, but is pretty straightforward when you find out which rails module originally provided the functionality usually bundled in Rails within the ActionController::Base.
That being said, let me give you an example of what i did for a small API project I did last week out of curiosity:
Initial Situation
We have a mainly finished Rails App. It all works fine, but it is basically monolithic. Everything is served by the Rails Framework. Luckily for us, all the model logic is bundled into a gem called core. the application essentially lets logged in customers create products which are than searchable through an end user view.
The goal was to provide a RESTful API for this, which can handle concurrency and larger data files (i.e. CSV, XLS) a little bit more efficiently.
Introducing Rails API
The design goal let me to the Rails API gem. The basic installation works like in Rails, except the script is called rails-api, i.e.:
rails-api new jsonapi
The advantage for me here was that I could use the core from the other application, but nothing would stop me from just introducing my own models to the jsonapi application.
That being said, you can do all the standard Rails goodies, like routing, etc. It follows the same convention. then again, standard routes initially react to JSON only, which can be a bit confusing at times.
Let me give you an example of the API Controller that handles products:
class ProductsController < ApplicationController
include ActionController::HttpAuthentication::Token
before_filter :find_product, :except => [:create, :index]
def index
render :json => #products
end
def create
#product = product.new params[:product]
if #product.save
render :json => #product, :status => :created
else
render :json => #product.errors, :status => :unprocessable_entity
end
end
def show
render :json => #product
end
def update
if #product.update_attributes params[:product]
render :json => #product, :status => :ok
else
render :json => #product.errors
end
end
def destroy
if #product.destroy
render :json => #product, :status => :ok
else
render :json => {:note => I18n.t("messages.deletion_impossible")}, :status => :unprocessable_entity
end
end
protected
def find_product
#product = Product.find params[:id]
end
end
It is nothing special. The only thing to note is the second line where ActionController::HttpAuthentication::Token is included explicitly. This is so that your aPI may be secured by HTTP Token. If you want to know more about securing an API, I suggest Ryan Bates' Guide on Railscasts.
In essential, you provide a before filter in the ApplicationController like this:
class ApplicationController < ActionController::API
include ActionController::HttpAuthentication::Token::ControllerMethods
[...]
before_filter :restrict_access
[...]
def restrict_access
authenticate_or_request_with_http_token do |token, options|
# see if key is valid.
end
end
end
Again, note the second line, you have to include the ControllerMethods manually, otherwise no controller will know about authenticate_or_request_with_http_token.
Extension
You may know extend the API based on the Rails conventions. It works exactly the same way, with the exception that some stuff is intentionally missing by default. I suggest adding JBuilder (Railscast), if you need more flexibility in your JSON Templates.
Great, but what about clients?
Personally, there is a lot of choice when it comes to clients. Ultimately I find that it comes down to what you like most. I can personally recommend a small node.js layer on top of the Rails API which then gets a single page application based on backbone.js in front of it. You can also try AngularJS if you like. You can also build another Rails App around it and call the API from within your controller actions.
It also depends on what platform you want to target - a native application for iOS/Android comes to mind.
The choice I made was node.js + backbone. It currently makes the most sense for me at the time and for the project. The node layer essentially holds the Token necessary to communicate with the API and the backbone application has a small library to talk with the node layer. It can however be a double edged sword, depending on how complex your API will be. For a small example this seems to be fine, but there can be a lot of code duplication just to put the calls from the backbone application through to the Rails API.
Authentication
For authentication you can make customer based API-Keys (Tokens) and then limit the controller logic to only accept data operations which are allowed with that key. You could than manage the session via the node layer. Edit: This is authorization, not authentication. Nothing actually stops you from using Authlogic with Rails API - i have not tested it, but it should work.
I confess that i have not finished this part yet - I hope others can answer this architectural question :-)
I hope I could provide some insights.
P.S.: If you want to test your API i highly recommend httpie (It's awesome!)
I'm building a simple Sinatra application to show some items stored in a database. I happened to find the gem sinatra-sequel that was supposed to make things easier.
To mantain the modularity I'm defining the Sinatra app in a file and the model in a different file. Unfortunately the model can't find the connection and mais my app crash. The same thing is described in this sequel-sinatra issue
I could define my model in the app class, but I prefer a more elegant solution if there is any.
I have a few Ruby scripts that process text files in different ways, that many of my friends find useful. However, most of the people I know are not comfortable running scripts on the command line. The easiest thing for them would be to create a simple webpage where people could upload a file, select a few options, have it processed, and then download the result.
I know it wouldn't be too hard to build something like this in Rails or Merb or something like that, however it seems like a very common problem, so I was wondering if there was already some kind of template, or similar application that I could easily modify, i.e. let the user upload a file, choose a few options, then {fill in code to do something with file}, let the user download the resulting file?
In the past I used Carrierwave to upload user avatars.
If you are used to Rails it's really straightforward.
Let it be a TextFile resource:
gem 'carrierwave'
$ rails g scaffold textfile content:string title:string etc etc
$ rails g uploader textfile
class TextFile < ActiveRecord::Base
attr_accesible :content
mount_uploader :content, TextFileUploader
end
And that is is pretty much all you have to do to obtain the app's skeleton. However, to answer your real question, no, I don't think there is already a rails app that does exactly that.
https://github.com/jnicklas/carrierwave
I found sinatra-fileupload, which pretty perfectly answers my question. It's a very minimalistic framework which works perfectly, I can just plug in the file handling, and change the layout etc a bit. There were many examples of sophisticated Rails plugins linked to databases, with versioning and stuff, but I really wanted the most minimal example.
I have a bunch of notes in Evernote which I would like to access in a Rubyish way (instead of only using the web interface). I thought I'd use this gem (https://github.com/cgs/evernote), which is "...a high level wrapper around Evernote's Thrift-generated ruby code. It bundles up Evernote's thrift-generated code and creates some simple wrapper classes."
I got a developer key, and the sample code here (https://github.com/cgs/evernote/blob/master/example.rb) worked, giving me the correct name for my sandbox notebook.
However, I don't understand what to do next. By "simple wrapper classes" I was expecting the Evernote::EDAM::Type::Notebook object to be some Enumerable object that I could use blocks to query. I dunno, something like
notebook.select {|note| note.tags == 'foo'}
But when I do the notebook.TAB TAB trick in IRB to look at available methods, there is nothing like that. The author of the gem refers users to Evernote API at http://www.evernote.com/about/developer/api/ref/ , and I can't make heads or tails of the thing. Am I out of luck until I fully understand what things like THRIFT means, or is there a simple listing of methods somewhere that I'm failing to look?
You shouldn't have to learn anything about Thrift. The data model wrapper classes (Note, Notebook, Tag, etc) are basically dumb structs; the methods to exercise them are on the endpoint classes, UserStore and NoteStore. For example, to get a list of Notebooks, you'd call NoteStore.listNotebooks. You can see some examples in the SDK under ruby/sample.
I've run into this issue recently, to use Ruby accessing the Evernote API. And here is the list which may help:
Official Ruby Demo
Evernote Developer Guide
Evernote API: All declarations
ENML
And I wrote a demo to make it more specific and straight.
Evernote API Ruby demo