Combining 2 rails apps to a single codebase - ruby-on-rails

Our company started out with a single product, a rails app backed by some java services, then decided they wanted another product that was initially considerably different than the first, but as time has gone on we've realized they are starting to converge, and making a code change to one requires a similar code change to the other for a new feature/bug fix. This is obviously becoming a pain.
In some cases we have gems that share some of this functionality but it goes beyond ruby into javascript, css etc..
So I'm tasked with merging these two apps into one codebase. I think eventually we'd like it to be a single app with permission based role access but that will come much later.
My first thought to quickly put them together is to create two rails engines and share common libs between them. I think this is the quickest way to combine the code, find common sections and start sharing.
My first problem though is how to route between the apps. One app uses a single domain name that never changes, the other app has many domains. Can someone suggest how I might route a particular request to a particular app so they can remain separate to start whilst sharing a common codebase of libs?
Or, if anyone has other suggestions as to a way to combine these apps I'm all ears.
They're both Rails 2.3.10 apps running JRUBY 1.5.3, but we're open to possibly upgrading to Rails3 if that would make things significantly easier or cleaner (ie with better Rack integration)
I haven't done any Rack programming but never hurts to learn if that will make our lives easier.

You should avoid sharing code on server level, best to do that would be building libraries including common code base and use them during development. Probably the best shoot would be using helpers as it is easiest way to provide modules that provide functionalities all over your code.
Regarding rewriting functionalities to one application, choose that one with bigger set of ready code as a base. It should be possible to migrate code per method using web server supporting url rewriting. I thought of using apache with mod_rewrite. So the plan would be:
Setup both applications to be accessible through one apache.
Chose one method that is similar in both and rewrite it in one application to support both applications requirements.
In apache add a mod_rewrite rule to redirect traffic to one application only on this action.
Go to point two till everything is rewritten.
Remove old application and adjust routing/mod_rewrite to use the one application
You do not have to use apache, there should be other web servers supporting url rewriting.
I was thinking of using this algorithm to rewrite our application to rails 3.0.

Your idea of using engines is what I would suggest.
For routing, I would handle it outside of Rails.
For instance, you would do the following in nginx:
server {
# Match only one host.
listen 80 default;
server_name YOUR_SINGLE_APP_DOMAIN;
location / {
upstream YOUR_SINGLE_APP_RAILS;
}
}
server {
# Fall thru and match any other host.
listen 80 default;
server_name ~^.*$;
location / {
upstream YOUR_MULTI_DOMAIN_APP_RAILS;
}
}

Related

App for managing apps (architecture)

I know it's gonna be a very broad question and I'm pretty sure this is not anything new in todays world, but I really don't now where to start on this one.
I've started working on a rails-based service that would allow users to create, configure and manage their projects (basicaly copies of a single app with customization). The projects would be run on a subdomain with an option of connecting their own domain. (Quite similar to how SquareSpace and Wix and many other website building services handle their websites)
I want these projects to be as flexible and customizable as possible (including the visual design, some additional features etc) while maintaing ease of setup and updates for the codebase itself.
So the questions I start with:
Should each project be a separate app (basicaly a copy out of the
same repo) with its own configs, database, nginx and unicorn
configs, etc. or should I keep all in 1 app and differenciate them
with different configs and maybe databases and assets?
If it's better to keep everything separated...
... what's the best setup process (provided that I have basic configuration to start with)?
... how would I be able to update them all (with bugfixes, new features, performance improvements etc.) from one place?
If I keep all the projects in the same app...
... how should I manage the configuration concurency between projects?
... how do I separate the data and assets?
As always, I'd be grateful for any sufficient help I can get.
I have no experience building these kind of things and maybe there is an easy solution I'm not aware of. But my answer may give you some ideas/pointers to start with.
1) It's hard to give an accurate answer but based on the high personalization criteria and the "copies of a single app" you talk about, I would go for an architecture more PAAS-like than SAAS-like. So separated apps.
2.1) You may want to consider a setting using:
A main rails app, with a main webserver and a main nginx conf. A wildcard domain.
A bunch of dynamically managed docker containers. Each container is initialized from your single app, and then personalized by the user. User is associated to its containers through the main rails app. When a container is created from the main app, the main nginx config is updated (i.e. by adding a file in sites-enabled which define a new 'server' that bind the open port of the new container, and the right 'server_name').
Each contained rails app ship an unique and shared rails engine. The rails engine is shipped by adding the corresponding gem in the Gemfile so it can be updated.
2.2) You update the 'shared rails engine' gem. You can then run bundle install in each containers.
People interested in these kind of setups may consider tools like dokku and deis.
Consider a multi-tenant architecture. We've used it effectively for fleet-genius.com.
The following link provides a good overview of the architecture from a Rails point of view.
http://blog.elbowroomstudios.com/zero-to-multitenant-in-15-minutes-a-rails-walkthrough/

How to run multiple "Applications" under one compoundJS instance?

I've been using nodeJS + expressJS for several years now developing a custom Application Platform for our organization. Our central framework provides a common set of services (authentication, language, administration, etc...) for any installed Modules/Applications under it.
I would like to switch our framework out with compoundJS. However I'm not familiar with the design constraints imposed by it (and Rails apps in general) and can't seem to figure out how to accomplish what I'm after.
I would like to only have a single server instance running: all
requests first process through our common authentication checking.
Then are passed on to an application's controllers.
I would also like to have each application separated out: preferably
under a separate site/applications/ directory. Each of these
applications could be designed using compoundJS normally. And I would like to install them like:
cd site/applications
npm install site-hr
npm install site-finance
npm install site-payroll
this would then have all the routes from /hr, /finance, /payroll operational.
How do I accomplish this?
Is there a way to get compoundJS to search the nonstandard /applications/* folders for models/controllers/views and load them while keeping the central /site configurations?
Or is there a better way?
Sorry for the late answer, but I needed something similar: I needed to put together tool applications in a portal.
I found a way to include child applications in a parent's Compound application as node modules. I wrote a guide on how to do it and sent a pull request to add it in the advanced folder of CompoundJS' guides. It is also available here. It requires a bit of work, but it works fine with 4 applications for us.
Hope it can help.
It's simple. Just use app.use in config/environment.js to map your sub-apps:
var mod = require('your-compound-module');
app.use('/subroot', mod());
When you visit /subroot/any-path, then it will be handled by /anypath route of your sub-app. Note, that you don't need any additional work on path helpers, as they will start with '/subroot' automatically (handled on compound side).
This is a good point, but we haven't seen any implementation yet. May be years later there would be some.
Using a proxy layer in front of the instances would be a general method, usually with Nginx, Vanish Cache etc. For the bleeding edge techs, I've heard Phusion Passenger has implemented Node.js support, but I haven't successfully tested yet. If you are familiar with Ruby, it would be a good try.
If you really want to construct a big project with many modules, you can try out some industrialized frameworks for instance Architect for Cloud9 IDE project.
For authentication, I think it's necessary to use independent methods in each application, but they can share with one user database.

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.

How to extend an existing Ruby on Rails CMS to host multiple sites?

I am trying to build a CMS I can use to host multiple sites. I know I'm going to end up reinventing the wheel a million times with this project, so I'm thinking about extending an existing open source Ruby on Rails CMS to meet my needs.
One of those needs is to be able to run multiple sites, while using only one code-base. That way, when there's an update I want to make, I can update it in one place, and the change is reflected on all of the sites. I think that this will be able to scale by running multiple instances of the application.
I think that I can use the domain/subdomain to determine which data to display. For example, someone goes to subdomain1.mysite.com and the application looks in the database for the content for subdomain1.
The problem I see is with most pre-built CMS solutions, they are only designed to host one site, including the one I want to use. So the database is structured to work with one site. However, I had the idea that I could overcome this by "creating a new database" for each site, then specifying which database to connect to based on the domain/subdomain as I mentioned above.
I'm thinking of hosting this on Heroku, so I'm wondering what my options for this might be. I'm not very familiar with Amazon S3, or Amazon SimpleDB, but I feel like there's some sort of "cloud database" that would make this solution a lot more realistic, than creating a new MySQL database for each site.
What do you think? Am I thinking about this the wrong way? What advice do you have to offer in this area?
I've worked on a Rails app like this, and the way it was done there was named-based virtual hosts, with db entries for each site running. Each record was scoped to a site if necessary (blog posts, etc.) while users would have access to all sites running out of that db. Administrator permissions could be global or scoped to one or more sites.
You're absolutely correct when you say you'll reinvent the wheel a million times during the project. Plugins will likely require hacking on top of the CMS itself.
In my situation, it ended up being a waste of almost a million dollars of company money to build that codebase to run multiple sites while still being able to cater to the whims of each client site. It worked, but was not very maintainable due to the number of site-specific hacks that subsequently entered the codebase. You may be able to make it work if you don't have to worry about catering to specific client sites running on your platform.
In the end, you're going to need a layer of indirection to handle the different sites regardless of methodology. We ended up putting it in the database itself. If you go with the different-db-for-each-site method you mentioned, you'll put that layer in your code instead. I'm not sure which one is the better method.
I hope you're able to pull this off. I failed.
Also, as I learned today, Heroku offers postgres instead of mysql for rails apps.
There's James Stewart's Theme Support Plugin for Rails 2.3, and lucasefe's themes_for_rails gem for Rails 3+.
I just started using the 2.3 version and it's working well so far.

Django, Rails Routing...Point?

I'm a student of web development (and college), so my apologies if this comes off sounding naive and offensive, I certainly don't mean it that way. My experience has been with PHP and with a smallish project on the horizon (a glorified shift calendar) I hoped to learn one of the higher level frameworks to ease the code burden. So far, I looked at CakePHP Symfony Django and Rails.
With PHP, the URLs mapped very simply to the files, and it "just worked". It was quick for the server, and intuitive. But with all of these frameworks, there is this inclination to "pretty up" the URLs by making them map to different functions and route the parameters to different variables in different files.
"The Rails Way" book that I'm reading admits that this is dog slow and is the cause of most performance pains on largish projects. My question is "why have it in the first place?"? Is there a specific point in the url-maps-to-a-file paradigm (or mod_rewrite to a single file) that necessitates regexes and complicated routing schemes? Am I missing out on something by not using them?
Thanks in advance!
URLs should be easy to remember and say. And the user should know what to expect when she see that URL. Mapping URL directly to file doesn't always allow that.
You might want to use diffrent URLs for the same, or at least similar, information displayed. If your server forces you to use 1 url <-> 1 file mapping, you need to create additional files with all their function being to redirect to other file. Or you use stuff like mod_rewrite which isn't easier then Rails' url mappings.
In one of my applications I use URL that looks like http://www.example.com/username/some additional stuff/. This can be also made with mod_rewrite, but at least for me it's easier to configure urls in django project then in every apache instance I run application at.
just my 2 cents...
Most of it has already been covered, but nobody has mentioned SEO yet. Google puts alot of weight on the URL itself, if that url is widgets.com/browse.php?17, that is not very SEO friendly. If your URL is widgets.com/products/buttons/ that will have a positive impact on your page rank for buttons
Storing application code in the document tree of the web server is a security concern.
a misconfiguration might accidentally reveal source code to visitors
files injected through a security vulnerability are immediately executable by HTTP requests
backup files (created e.g. by text editors) may reveal code or be executable in case of misconfiguration
old files which the administrator has failed to delete can reveal unintended functionality
requests to library files must be explicitly denied
URLs reveal implementation details (which language/framework was used)
Note that all of the above are not a problem as long as other things don't go wrong (and some of these mistakes would be serious even alone). But something always goes wrong, and extra lines of defense are good to have.
Django URLs are also very customizable. With PHP frameworks like Code Igniter (I'm not sure about Rails) your forced into the /class/method/extra/ URL structure. While this may be good for small projects and apps, as soon as you try and make it larger/more dynamic you run into problems and have to rewrite some of the framework code to handle it.
Also, routers are like mod_rewrite, but much more flexible. They are not regular expression-bound, and thus, have more options for different types of routes.
Depends on how big your application is. We've got a fairly large app (50+ models) and it isn't causing us any problems. When it does, we'll worry about it then.

Resources