Distributed Resource in Rails - ruby-on-rails

I am planning a system that requires collaboration between many local Rails apps. The design calls for a global app to relay RESTful requests between these servers.
For example, imagine each school having a local Rails app, including a Teacher resource. I propose a global app which provides access to teachers as: /school/42/teacher/3
The School resource on the global server has a field for the base URL of the app at each school, so it can relay such a request to school_42_url/teacher/3.
The design calls for relaying, rather than having school servers connecting directly to each other.
I can think of several ways to achieve this but, being new to Rails, can't work out which one is 'the Rails way'.
ActiveResource is appealing, but seems to require a fixed 'site' rather than setting it for each request.
Routing, perhaps with URL globbing might work, but I need to see an example of how to achieve this.
A third approach would be a custom Controller, but this doesn't feel like the Rails way.
To be clear, the combination of {school_id, teacher_id} is globally unique, but the global server need not store details of teachers, those are treated as a web resource.
Comments or suggestions welcome.

You should use rails RESTful architecture on your client apps to expose apis (xml, json), and some library like Net::HTTP to call those apis from your server(main) app.

It sounds like Pow may be what your looking for. It allows you to configure URL's for stack and rails application via symbolic links. It fits well in the rails model and may allow you to build your independent RESTful applications in the manor specified. I know their are methods for having independent rails servers work together but based this is a very low overhead approach and may be the way to go at-least for testing and development purposes.

Related

What is the conventional architecture for a Rails 5 API with an Administrative UI as well?

I was setting out to start a new Rails 5 API, and realized I also need a content-administration "site" of some sort. The admin tool is very simple, just a UI for very basic CRUD operations.
I have an instinct to create two separate Rails applications - one web application for the content-admin tool, and another web application for the API.
This brings about the problem with sharing data models, which is solvable by using rails engines, or including the models as a gem.
As I was researching solutions, I seemed to observe a pattern of including the content-admin portion within the API app itself. There are some middleware includes and controller inheritances involved in this, but its quite simple to get a content-admin UI to run within the same app as an API. Its much less work, and I dont see much of a problem with scale, since the content-admin UI is lightly utilized and the API is the core of the business.
Is this the accepted convention? I might be gaining a bias due to web search results, but it seems like the simplest and most common approach. I plan to have a separate server for accessing the content-admin vs accessing the API, which is what led me to originally plan this as two separate apps. Now I am thinking I was just getting sucked into the "microservices" hype, and it seems more conventional to just include the content-admin UI with my API app.
On the other side, everything I read about Rails engines is 3-4 years out of date. There is little information (that I am stumbling upon) within the last year or so, and more specifically, little-to-no information concerning Rails 5. I am wondering if this sort of architecture has fallen by the wayside.
Is there a typical convention for Rails 5 API applications that also need a content-admin UI?
The approach I've used before is to have the api running out of /app/controllers/api and then have the ActiveAdmin gem installed, with the admin interface files in /app/admin. You can set up the routes to serve the admin interface at https://api.yourapp.com/admin and the API at https://api.yourapp.com/api/v1/ or similar.
I don't know how much of an accepted convention this is, but it works fine.

Rails REST API Practices

I've come across two scenarios with regards to creating a REST API in Rails and I wonder which one is preferred. Usually
if you know that you're required to have a REST API for your application at start. Does it make sense to have it in a namespace and thereby duplicating the controller logic?
I've seen examples where people have an application already and later figure they need to extend and offer a REST API. The approach to this has been to create new routes with namespacein routes.rb and controllers/api/whatever.... This still yields duplicate code though, but might be more sensible approach. The difference being a stateless machine for the REST API calls.
Can anyone elaborate on the preferred approach, thanks.
If you create a Rails application, and following the usual conventions, you basically end up with a REST API. Unless you are talking about a more specific meaning of the term (which I am not aware of), "REST API" is more a bunch of general characteristics of the API (i.e., things like statelessness, resource-based URIs if using HTTP, etc.).
So to turn the question right back to you: which case are you thinking about where a (conventional) Rails application is not by extension trivially a REST API?

CakePHP and Rails: slowly port old php functionality to new rails

I am a rails developer working on a cakephp site. The more work they send me, the more php code I write and thus the more dependence on php we introduce. What I want is to stop writing new features in php and start writing them in rails. Our resources are limited and the existing php site is huge so a full port from cake to rails is not possible.
Is there some way to write new features in a rails app while maintaining and allowing access to all the functionality of the old php (and vice-versa)?
It seems I would need a route aware app to traffic requests to either php or rails, but then we run into the issue of, for example, existing user functionality written in php not being available to the rails app and vice-versa.
What about something to translate ruby into php? That way I could start writing my model stuff in ruby/rails rather than php.
I feel like my question is muddled by the fact I do not know how to ask the questions I want to answer, so hopefully this is understood.
As always, thanks in advance!
One approach that you may find useful is to leverage the power of your web-server to properly re-write and delegate requests to two different systems. If you can design your new Rails application to use the same database records as the old one, with models mapping to the old tables directly, and ensuring that sessions established by one are valid in the other, you have a lot of latitude in how you go about doing this.
Apache has a very full-featured URL rewriting and proxying system that can be configured to direct "legacy" parts of your site to an existing set of PHP scripts while directing all other traffic to the new Rails application. You will need to be careful to ensure the design of both applications are nearly identical or it may seem strange to users.
Another approach that helps ensure a consistent appearance is to strip out a lot of the theme from your PHP application. By creating very bare-bones pages that only expose the required functionality on each page, Rails can fetch these by passing through any relevant session authentication information and re-frame them in the right layout.
This way you can preserve existing functionality and have it embedded inside your new application. You can use something as simple as open-uri or the curb gem to handle this HTTP-level delegation.
You would end up with controllers that look like this:
class PaymentController < ApplicationController
def index
#content = fetch_legacy_url('/payments/index.php'))
end
end
The fetch_legacy_url method would create an HTTP fetch request that includes the required headers, cookies, and so forth, and return the response body. Your view then ends up looking something like this:
<%= #content =>
From there you can shunt parts of the PHP layout over to the Rails app piece by piece. For instance, ripping out large chunks of static HTML and putting them in the Rails template would reduce the amount of actual PHP code you have to port.
It's a bit messy to maintain two applications in parallel, but as you point out the alternative is to keep accumulating technical debt and making the inevitable re-write that much more significant an undertaking.
The first step would be to experiment and see if you can create a Rails environment that uses your existing data, or at least the data relevant to the new functionality you intend to build out.

Scaling Out: how to handle communication between Ruby on Rails applications?

I am running Ruby on Rails 3 and I have an application that makes use of namespaces in order to handle more "internal concepts". With "internal concepts" I mean that each namespace is used to handle a specific resource of my application. For example a namespace is "users" and it is used to handle user's sessions and authorizations, another is "blogs" and it is used to handle all about posts and comments.
I think this is a "convenient" solution to avoid a lot of problems, but not the best.
At this time my RoR application consists of this file system structure:
# "users" and "blogs" are namespaces
RAILS_ROOT/app/controllers/users
RAILS_ROOT/app/controllers/blogs
RAILS_ROOT/app/models/users
RAILS_ROOT/app/models/blogs
RAILS_ROOT/app/views/users
RAILS_ROOT/app/views/blogs
...
I would like to switch the "users" and "blogs" namespace in two RoR applications using subdomains to have something like this:
http://main.com # This is the main RoR application
http://users.main.com # This is another RoR application used to handle users
http://blogs.main.com # This is another RoR application used to handle blogs
In few words, I think I am trying to Scale Out* my application or maybe to create a Webservice for each RoR application, but my issues are:
1. What problems I may encounter?
I noticed of problems about maintaining sessions (in my case I handle those with cookies) between applications but I think it isn't the only one problem.
2. How to handle communication between the three RoR applications in my case?
I noticed that I can use ActiveResource to share information, but I must pay attention to information such as user authentication.
I have to implement the OpenID/Oauth protocol in order to maintain user authentications?
I think I have to ensure the user authentication information with a HTTPS connection also if the comunication is between subdomains. Is it true?
3. How do I organize my work and resources?
With all that being said, I would like to don't use (absolutely) plugins or gems, but, if I need, I would like to implement my own handler.
At the end I would like to have 3 RoR "easy" and separated applications without use namespaces in each of them and that can communicate between each other:
# "Main" application for http://main.com
ROOT_MAIN/app/controllers/
ROOT_MAIN/app/models/
ROOT_MAIN/app/views/users
...
# "Users" application for http://users.main.com
ROOT_USERS/app/controllers/
ROOT_USERS/app/models/
ROOT_USERS/app/views/users
...
# "Blogs" application for http://blogs.main.com
ROOT_BLOGS/app/controllers/
ROOT_BLOGS/app/models/
ROOT_BLOGS/app/views/users
...
BTW: is a good approach the usage of namespaces that I'm doing?
P.S.: If you need some other information, let me know and I will update the question.
*From The O2 Software Process: "Scale Out" refers to the concept of adding more servers to an existing park, as opposed to "Scale Up" which means to replace existing (slow) servers with newer (and faster) servers.
You problem is lot more simpler than you think. It all depends on how you handle your routes.
Ruby On Rails 3 has better support for Subdomains. So, you need not separate them into three/more RoR apps. You can put all your code in one single RoR app. And redirect user.abc.com to any controller like "users/sessions", redirect blog.abc.com to "blogs/blogs" controller. namespaces are convenient in apps like yours where they make your job really quick to separate out contextually different parts of your app in different folders and route formats.
Try the namespaces to your hearts content, I believe you won't get any errors you are imagining right now. I'd suggest you write code for it and come here if you face problems in it.
Is your app really so big that you need to use multiple apps to handle the different concerns? It could be that your post just lacks enough detail to convey the real magnitude of what you are doing but it seems like you are trying to modularize a small enough app that it would be fine without "scaling out" as you say. Or maybe I am just missing something?
I think that is going to be a tricky problem but there may be some way to store session data in the database and either share it the way you handle #2 or you'll have to roll a custom solution for that. I think the biggest problem will be sharing resources across your app, and also if you are breaking user management out into its own app you'll need to implement your own OpenID/Oauth. This post describes this with Devise/OAuth.
You can use activeresource to connect to each app's respective rest api. This post describes one guy's solutions to sharing data across rails apps.
This question is somewhat vague. You described using multiple apps to separate your concerns (blogging vs user management), so I imagine you'll have your resources at the root of each application without any namespacing, as you've done already in your existing application.
Now for a more general response to your entire question, recently I read a blog post regarding Data, Context and Interaction (wikipedia article) on Rails, and I think this might be a better solution for what you are trying to accomplish if you feel like your app is getting out of control.
Sorry for answering this late.
Actually if you want to scale your rails application you need not create different apps for each unit(I mean as you are trying to separate out users and blogs here), you are jumping a step ahead in the process of scaling your app you should first put all individual units as mountable engines and require them as gem in your core application and mount them in your core app routes.As in your case blogs can be moved to a separate mountable engine.If in future you require to scale more then you can move futher to use engines as separate application.Here's a link to a video that may give you idea what I am trying to explain here https://www.youtube.com/watch?v=pm94BsoMGik

How to turn a single-site app into a mantainable multi-site app without code changes?

It's an application that we use internally at the office that I would like to offer as a hosted service for anyone.
How can I do that without making major code changes?
The first thing that occurs to me is to have the app select which database to connect to based on the domain.
So each instance of the app would have its own database, but all instances would share the same code.
The only changes required to the code would be the database selection.
Is this approach maintainable? I've heard wordpress.com does this and that it offers a couple of advantages. I'm mainly looking to do it this way to avoid have to scope my entire set of database queries to a certain site within the same database.
Thanks!
The simplest way to do this is to clone the application, and create another server instance to handle it. This actually the way I handle multiple wordpress blogs on my server
Pro:
This process can be streamlined into a utility script.
Can be easily maintained if symlinks are used for the common code. IE: Everything but branding and some of the things in the config directory.
Cons:
- If you're using passenger it will require an apache restart for each new instance.
- Same if you're using Apache to route subdomains on different virtual hosts to different mongrel clusters.
However the better way comes from the question: Rails - Separate Database Per Subdomain
The method in the accepted answer is much more robust. It might require more changes than you're looking for, but it has all the benefits without the drawbacks of any other methods. Each new instance requires a new entry in the master database with the table name and other instance specific information. You'll also want custom rake task to build the database for each new instance.
I would suggest switching the database connection and adding a view_path based on the domain, I have posted code in this question.
I hope this helps!
I wouldn't do this with multiple databases as you mentioned. Keeping all your schemas/migrations in sync with all the db's could become painful.
I would look into simply making it a multi-tenant app where you have some sort of "Account" model and then all your existing models are scoped to it ... in other words, if this was a blog app, your Account has_many :posts, etc.
With this approach, you can identify accounts by subdomain ... have people choose their subdomain when they create an account and go from there.
It's pretty straightforward to do. If you need add billing into the mix, you might look at the SaaS Railskit (which handles all the signup and subdomain stuff) or Chargify.
You can also identify accounts Twitter-style ... with http://myapp.com/someuser

Resources