How to manage differences using same code base for multiple Rails 2.3 websites - ruby-on-rails

We have a website using Rails 2.3.x, bundler, nginx, passenger and git, and would now like to use the same code to deploy a very similar site. Differences between the two will include:
Locale
Databases
Validations in some cases
Views in some cases
What is the best way to manage these differences while using the same code base?
Some ideas we've had:
Create new Rails environments, such as production-a and production-b and handle differences in the appropriate environment files. One potential problem is that many gems and plugins are hardcoded to look for production or development environments.
Use Passenger to set a global variable or use the domain per request to determine which context to use. The problem with this are rake tasks, cron jobs, etc that would not have access to this state.
Maintain two versions of the config directory. This would be inconvenient maintaining 2 versions of all the config file, many of which would be identical. Also, I'm now sure how to leverage git to do this correctly.
Any ideas, tips, or examples would be greatly appreciated! Question #6753275 is related but seems incomplete.

One solution I have used in a rails 2.3.x project was to convert the entire site to an engine. That actually is pretty easy, create a folder under vendor\plugins\ and move all the app stuff there. You can see an explanation for rails 2.3 here.
If needed you can even move all migrations and stuff there as well, and use a rake task
to run those.
Everything that needs to be overruled can then just be placed in the actual rails project using the engine. So you would have two rails-projects, with their own configuration, locales and some local overrules, and one big shared plugin/engine.
We used git submodules to keep the code in sync over different projects.
In rails 3 this is even easier, since the engine can now just be a gem.
Hope this helps.

Related

Nesting Ruby gems inside a Rails project

How do I create a gem project nested inside my current Rails project?
I've got a Rails project with several parts that could easily be gems. I would like to extract these parts into gems but not leave the current Rails project. Creating new source control repos for the gems add additional complexity that project or organization is not ready or able to handle. These complexities will be overcome at some point and I would like to be ready.
So far I can only think of these items.
Relocate code to a single directory root. I'm guessing this would be in the vendor path
Create a <something>.gemspec
Link to the gem in the Gemfile of the Rails app
gem 'my_lib_code', path: 'vendor/my_lib_code'
What else do I need to do? I'm sure I'm missing something important.
If this were a c project I would create another shared library that the make process spits out. Or if this where a c# project I would make a .dll. For Java I would...
I'm sure Ruby can do the same as all the other languages. Something that is a half way step between a normally fully extracted gem and just some code siting in my lib path.
This is a perfectly fine approach for a component-based architecture.
You have a single repository, a single test suite, and a single deployment process, while at the same time you are "forced" to think of clean interfaces and separation of concerns.
Of course if you are planning on sharing this functionality with other projects, an externally hosted (but not necessarily public) Gem would serve better.
Implementation wise, you can get some nifty ideas from Stephan Hagemann's talk at this year's RailsConf: "Get started with Component-based Rails applications!"

How to automate rails project "bootstrap" consolidating routine customizations?

As we create more Rails applications, I find myself routinely adjusting the project generated by rails new ... in exactly the same ways: adding rspec, capybara + capybara-webkit support, adjusting config/application.rb to our tastes, including several gems we came to love.
I had a look at suspenders, it's a good starting point, but some of their choices differ from ours. Plus it's flexible in places where we don't really want any choice. In fact we'd rather have a couple project boilerplates sharing some customizations and each adding some unique extra's.
What are the options for streamlining/automating a project "bootstrap"? How could we organize a set of boilerplates and let them evolve as our preferences change (not adding options, but changing which made choices are hardcoded)?
I'm thinking in the direction of scripting what I normally do manually starting from rails new, editing the Gemfile, config/application.rb etc, but may be there is a cleaner (future versions compatible) approach or tool?
I really like using the Rails Composer gem/tool for this.
At the basic level when you run Rails Composer it will ask you a series of questions about what gems/configuration options you'd like your new Rails app to have. Then generates your app for you.
I like the "ask me for what I want" approach because different Rails projects may need different things: Postgres vs MySQL, Bootstrap vs Zurb Foundation, etc. 90% of these are usually the same, but it's the 10% difference that gets me.
At the more advanced level, Rails Composer shows you how to use Rails templates to create your own standard modifications, or you could fork Rails Composer to add the options you want (maybe sending a PR back to the project if it's something useful?)
At the expert level, Rails Composer has "starter apps": just pick one of those and go, choices already made for you. Depending on your needs this might be just the kind of thing you're looking for -- digging into how these "starter" apps are created and making one yourself.

Preferable way to distribute a Rails app

Although Rails and PHP have different deployment methods, what is the preferable way to distribute a FOSS Rails app? Suppose one of the major PHP apps - Magento, Drupal, Wordpress had been build upon RoR, what would have been the preferable way for them to have distributed their application?
Packaging up the code as a gem seems to be the wrong approach for a complete out-of-the-box application, but I could be wrong.
Coming from the world of PHP with its upload-and-go approach, and being a newcomer to Rails, it's rather opaque at the moment to see how code could be easily and effectively distributed.
Packaging a completed Rails app as a gem is probably the wrong approach. I think the best solution is to provide access to a git repository or a tarball of your git repo.
If you want to offer your users something more than rake db:schema:load to setup your app it's pretty easy to create custom setup commands.
Many applications are packaged with the source code just like typical PHP applications. While deploying Rails applications may seem difficult its expected that the user will know how to set up the server properly according to their environment and needs. The only issue you need to worry about is distributing the code, setting up the server is not a domain that you are going to want to help with.
For information on deployment in Rails you should see the deployment page here.
Well, usually Rails apps run in environment running Apache + Passenger (aka mod_rails).
Deployment is easily done with Capistrano gem.
When you're running Rails app in shared host environment, they usually use fcgi/cgi dispatchers to run Ruby.

Share visual assets along with some controllers between two rails apps?

I have two rails apps that I am thinking about merging into one because they share a similar layout. Right now there is a script in one app that pulls the resources from the other app (including a base controller) into the second app. There are a few ways I have been thinking about doing this:
Merge the apps with namespaces and upon deploy have a script that creates two separate RPM packages (this is for deployment on CentOS/RHEL) with the appropriate files in it
Run one app as the engine of another. Put all the shared controllers and visual assets into the top-level app. Upon deployment rip rip out the engine if I don't need it. (i.e. if it is just the first app and I don't want to give the code of the second app)
Create a GEM with the common controllers and CSS/JS and find a way to inject it into each running app.
Any thoughts/ideas? I am thinking of going with number 1 as it will probably be the easiest for development (2 would be easier for deployment I think)
At Brighter Planet we do (3). Our shared layout gem supports both Rails 2 and Rails 3.
In particular you'll want to look at:
lib/brighter_planet_layout/rails.rb which helps Rails 2
lib/brighter_planet_layout/railtie.rb which helps Rails 3
lib/brighter_planet_layout/rake_tasks.rb which helps you copy shared files into Rails 2 public dirs
How about 4: make three engines (or gems, or engines encapsulated in gems): one for the common stuff, and one for each application's unique stuff?
Have you considered creating an engine with the common controllers, css, and js, then packaging the engine as a gem. When you are working locally, you can have both apps point to a shared development copy of the gem using bundler. To deploy, package the gem with each app, and deploy the whole thing. There are a lot of benefits to doing it as a gem, like the ability to have different versions of the gem in the future so you don't have to update both apps at the same time.
This seems like a pretty decent engines guide: http://www.themodestrubyist.com/2010/03/05/rails-3-plugins---part-2---writing-an-engine/.
I'd be very leery of it, and would probably go with the above approach, but you may consider using symlinks to permanently pull files into one or the other of the projects. I think it's a bad idea, but in some narrow cases it might make sense. It really depends on your exact situation since it's kind of a nasty hack, but nasty hacks can sometimes solve specific problems eloquently.
Most importantly, I'd recommend not merging the apps. The scenarios of modifying the package on deployment to separate the two apps is error prone, and counter to current quality control procedures-- you want the code you develop to match the deployed app as much as possible.
Given that, you want to look at the different modularity approaches. There are actually lots of options for sharing code:
gem
plugin
library code included with a git submodule or equivalent
rails engine
separate deployed app
Probably a shared engine packaged as a gem is the nicest way to go, but it requires you be on the right version of Rails to get the full benefit. Even without an engine, you can get this to work... it'll just take a little more setup.
By "separate deployed app", I mean a third application that has the shared functionality. This may be the needed resources (CSS, JS), and can even be portions of the pages (loaded dynamically). This is potentially a funky solution, but I've seen it work in the right situation.
And any of these solutions requires a bit more effort on the developers' part... but in the end it's better the deployment troubles you'd get by mergine the code bases

What does "dispatches" files in rails src folder mean?

I just look up at rails sources and find folder named "dispatches". There is four file in it. I want to know purpose of this files. I know I use this files on my production server, but I never used to think of their purpose. I know there is something about attaching Rails app to Apache server. On my production server rails appname command add this files to public folder automatically. Can I set up this behavior on my development machine?
The rails dispatcher is the entry point for a rails application and is used to bootstrap the environment.
They have a long history and in a lot of ways they are almost obsolete. In days gone by rails apps used to be powered using cgi or fastcgi, which was a way for the webserver to communicate with a rails process. The boot process would be initiated by dispatch.fcgi or dispatch.cgi. Nowadays people are more likely to use apache/nginx+passenger or apache/nginx+mongrel/thin. (Does anyone still use lighttpd?)
I'm a little fuzzy on how dispatch.rb is used, but I think it's used by upstream rails servers such as mongrel/thin to bootstrap the rails process. However, now that rails is rack compatible I'm not entirely sure if that has changed.
You don't need to pay the dispatch.* files any attention.
I hope this helps.

Resources