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
Related
I have written some Rails API little long ago. I used namespace,module for making different versions of it.
Now I need to move my APIs to next version. Where I need to use different gems to achieve the requirement(need to add and delete some extra gems). While keeping the present version running for some more time.
I can use namespace, modules for routes and business logic changes. But how can I specify different gems for this version of API?
Does creating a separate git branch is the solution?
or
should I use different Gemfile.
How should I achieve this?
In same application if you want to add a new Gemfile, then I think it will be better option to create a engine and keep it inside vendors folder, so it will be inside your application and you will get separate routes, namespaces and Gemfile for that.
You can check the link given below about engine development.
http://guides.rubyonrails.org/engines.html
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!"
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.
I have a number of view helpers I use on almost every project, a set of useful rake tasks, minor extensions to active record, extensions to some gems (inherited_resources).
I'm wondering, what would be a good way to manage these 'snippets'? I wouldn't want to manage a gem for each snippet, or even a gem for each 'type' of snippet. Would it suffice to bundle this into a personal gem? Maybe add the option to specify which helpers/extensions to include in the project?
I could use a 'template' application which I could bundle with this code, but the problem here is if I update a snippet on one project, I want to be able to rollout that update on all projects with minimal effort (i.e. bundle update).
With your requirements, I would bundle it all in a base-zenph-gem and use it in every one o your projects, as it is the best way to have synchronized code over different projects.
Also, make a good documentation for it, as if anyone inherits one of those projects would love to know what is going on.
Instead of a gem with Rails you can create an engine which contains reusable functionality, then you can specify the use of the engine within your applications.
You can read more about it in the Rails documentation: Rails Engines
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.