How to run multiple "Applications" under one compoundJS instance? - ruby-on-rails

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.

Related

Share code/configurations/conventions/gems between Rails apps

THE PROBLEM
First a little bit of context: I am currently working as a freelancer, developping webapps using Ruby on Rails. Because I am working solo, the need to optimize my workflow is pretty important.
That's why I have always had the same question since I begun working with Rails:
How can I share code/configuration/conventions/tests between my apps?
More precisely, I want to share:
common gems that I always use, with their configuration
common integration tests, to ensure some conventions
common view helpers, test helpers, extensions to the core classes, javascript/sass partials
common files: .gitignore, git hooks, .eslintrc, configuration files of my CI etc
Some concrete examples of what I need in all my apps:
disable turbolinks by default, to add it later if need be
use javascript instead of coffeescript
use slim instead of ERB
install/configure capistrano
install a CSS framework (bootstrap, bourbon + neat + refills)
So far I don't really have the need to share models nor controllers.
I don't want to share behavior or functional components of the system itself, I am not looking for a micro-services architecture.
I have found that so far when creating new applications, all this setup work does take me a lot of time. Also, I would like to apply it retro-actively to existing apps when I add something new.
I have done quite a bit of research, but I haven't found a lot of answers. Many people are trying to share models, but few people seem to want to share a common ground between all their apps. Finding the right keywords may have been the problem though.
It seems to me that Rails is really good at DRY within an application, not so easy when trying to DRY between applications.
POSSIBLE SOLUTIONS
1 - Rails application template
The solution I am using right now, described in the Rails Application Templates guide, using the same API than the Rails generators described in the Creating and Customizing Rails Generators & Templates guide.
That's the solution used by Thoughtbot, with their popular suspenders gem. In the case of Thoughbot though, they have years of experience to draw from, have many employees and their common setup does not change that much.
Pros:
saves a lot of time when creating a new application
really nice API
Cons:
a lot of duplication: all the apps have the same common code, with the problem of this code getting out-of-sync
not retroactive: useless to add a common feature to already created apps
heavy maintenance work: my current workflow is to go through the git log of my apps once per month, and for each commit that could be common to all the apps I have, add it to the application template, and add it to the other apps manually
So far this solution is not that bad, because I only have two applications. But once I will have more, I will suffer from more and more overhead.
A better solution would be maybe to create a generator/rake task for every common new feature, to be able to apply it quickly to existing apps, and call it directly in the application template for new apps.
I haven't tried it though, and I am not really sure it will work. For example what if I want to propagate a one-line change in an existing common file in all the apps?
2 - Rails Engine
I have tinkered a bit with the Rails Engines to share code.
I have not understood from the Getting Started with Engines guide if I should better use a --full engine or a --mountable one for this specific purpose.
Pros:
once I update the gem version, all the changes are made available to the app
DRY: all the common code is in a unique place (the gem)
Cons:
the gems I would like to share are put in the *.gemspec file, which has not as many features as the Gemfile (from what I understand)
overhead caused by the need to update the version of the gem in all the apps, migrate to the new API of helpers, etc
no way to share non-rails files (.gitignore, git hooks, .eslintrc)
This solution has too many important shortcomings.
3 - Hybrid solution: Rails Application Template + Rails Engine
Maybe the best would actually to use both the above solutions.
In the gem share helpers and tests, in the rails template share the gems, their configuration/files and other files (for git, linters, etc)
It is indeed adding more complexity and overhead...
4 - Use git subtrees
Some people use git subtrees to share folders between multiple webapps.
Cons:
one has to share whole folders, not easy to share everything I would need, in their different target directories in the rails app
seems a bit "hacky" to me
Conclusion
Is there another solution than the ones I mentionned above?
What do you think would be the best way to do it?
How about having a blank "Master" rails app in the git somewhere. With all the settings and configurations you'd like to share. When creating a new app from scratch, you can merge the "Master" into it to apply the defaults. When you have an existing app, same thing, just merge and resolve conflicts as needed.This also gives you the ability to override the merged code if needed to.
Few things I can see wrong with this approach though:
Rails application name could cause a lot of headaches
Any updates could cause merge conflicts
I created a tool to deal with this when working in nodejs projects. But the tool is really just a command line tool so you should be able to use it.
https://github.com/tomasbjerre/dictator-builder
It is a concept with creating a dictator that dictates parts of your code base.

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/

A pre-built extendable web application for Rails?

I am wondering if there is a standard pre-built web application for Rails which has all the basic functionalities like user login, user profiles, profile image uploader, comments, search, maybe payments and a set of other usual web application features all bundled and ready to use and extend.
I like how Twitter bootstrap comes with a set of pre-built interface functionalities and styles, which you can start using and modify later. I am looking for something similar that can allow me to quickly set up a working application and go from there.
Does such a framework exist?
There are numerous examples out there.
However, there are two things you should really do:
Read the license to make sure you can use it they way you are thinking of using it.
Ensure you understand the design decisions and choices the original authors made. You will end up in a world of maintenance pain if you just copy cargo-cult style without understanding the tradeoffs others have made with their design decisions.
Any one of the links listed has enough to get you started. They may not have all of the features you listed but together they probably have all of your bases covered. You will have to put in some effort to get all those features working together though.
The RailsApps project is great because they all have tutorials that walk through the basic setup. They are also all built using the Rails Composer tool, which lets you pick and choose certain options for your app.

Combining 2 rails apps to a single codebase

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;
}
}

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.

Resources