Nesting Ruby gems inside a Rails project - ruby-on-rails

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!"

Related

How to convert a large gem to standalone rails app

I'm building a social network and have been using the gem community_engine but have been having trouble implementing the large amount of customization that I need for my app. I figure this will make it easier for me to override and add methods, as well as help me to better understand and learn from the code since I will be able to actually see all of it in action.
So far in my attempt I downloaded the source code, added the default bin directory and config files that were missing, as well ass all the gem dependencies.
What else do I need to do to get the app to work? I realize that there may still be a lot and that it might not be easy to explain, but at the very least is there any sort of documentation out there that might help me understand how to convert the gem to a Rails application?
Heres the community_engine repo: https://github.com/bborn/communityengine
Because this idea may draw some criticism, I'll add that I was originally building the app without any huge plugins accept for devise however I'm running out of time to finish this.
More stuff I've tried:
Moving files to a new rails app, got server to run but encountered many seemingly random errors, fixed a few but more just seem to pop up that I cant figure out:
I also took a look at http://guides.rubyonrails.org/plugins.html but this gem seems to go beyond that.
I would suggest that you clone the gem and begin copying files from the gem into your a new Rails application.
The engine gem probably has a similar structure to a Rails application, so you should be able to move the files from the corresponding folder to the same folder in your Rails root folder.
You may need to move gem files out of modules, change namespaces etc. Relevant folders to look at files you'll want to include might include app/ config/ db/, any gem dependencies in Gemfile or the gemspec file, as well as spec/ or test/.
Beyond that I think there's no silver bullet answer to your question, you're just going to have to work through problems until you have this up and running, and perhaps ask subsequent questions if you hit on an obstacle that you don't get beyond.
I think what you're looking for is a way to hook your Rails Engine into a rails app. The Hooking Into an Application section of the Getting Started with Rails Engines guide should be exactly what you're looking for.
Here are two additional resources on Rails Engines.
A Guide to Rails Engines in the Wild
Rails::Engine - Ruby on Rails API

Looking for something like RailsAdmin, but lighter-weight and not in the same process as the main app

We've been using rails_admin for a project for a year. It's good, but it would be preferable to have an admin interface that ran in a totally separate process from the main Rails app and from a completely independent code base. rails_admin has so many dependencies that upgrading it along with the main Rails app has proven brittle.
So the functionality we would need is just basic crud for the database tables, with a little bit of magic to make editing associations easier.
Are there any light-weight solutions out there for this? Bonus points for being lightweight & Sinatra-based rather than Rails-based.
I would look into git submodules or subversion externals. The way I've done something similar to this is to
List item migrate the models into a standalone ruby project.
put them in a 'core' subdirectory/module.
Create a new rails project just for administration.
Share the models between the 2 rails apps using an svn external of the 'core' directory into each project's app/models directory.

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

Should I create a Ruby gem or plugin

I have some logic code that is literally cut and pasted across several different sites I own (it's code that interacts with a web API I've created). Considering that this isn't DRY and that when I update one thing I want it to update across all my sites I wanted to move this to a gem or a plugin. My main question is which one is the best to use in this scenario?
One big sticking point is that this code is private and shouldn't be made available to just anyone.
Thanks
Gems are the de-facto standard for packaging and releasing Ruby libraries.
There used to be two major drawbacks to using gems instead of plugins in Rails applications. Gems did not have access to all the functionality that plugins had. For example, in Rails 2, gems could not directly add rake tasks to your application. In Rails 3, plugins and gems are completely equal.
The second drawback was that gems were harder to bundle with your application. This has been resolved a while ago by rake gems:unpack:dependencies. It copies all gems your application depends on to your app's vendor/gems application. If you deploy these with your application, there is no need to install them on remote servers. In Rails 3, the new gem bundler further improves this mechanism. It even allows you to bundle Ruby C-extensions!
Also consider the things that cannot be done with plugins: versioning, packaging, dependency management, extending Ruby, etc.
In my opinion there is no serious reason to use plugins instead of gems anymore. The last advantage of plugins will be void when Rails 3 is released. Spread the word, and help everyone convert their plugins to gems!
Let's see Pros / Cons:
Gems
Pros
Easier to update the version (gem update)
Code encapsulated and available for all applications on the machine
Cons
Webapp code and gem code aren't encapsulated together.
You have to install every gem on each pc the application will run.
You have to install rubygems on each pc, too.
Maybe it's nedeed to be sudoer to install the gem.
Plugins
Pros
Code encapsulated within the application
You don't need special rights on the machine to work.
You don't need rubygems.
Cons
More difficult to update the code than gems
You have to install the plugin on every application that will need it.
I think this are all the differences. The decission now is yours :)
For me both solutions are OK, you have to think about your needs.
Hope that helps.
Will you ever have more than one version of this API being used in production at the same time?
If not, the simplicity and flexibility of a plugin is probably easier, especially if you use a tool like Piston to install/update the plugin from a centralized code repository.
Gems are not too convenient for private stuff, imo, with the way they're distributed. And distributing them by hand avoiding the gem hosts is an overhead. If it was me and I had a piece of private code I need to use in a bunch of places, I'd simply throw it into lib/ dir as a fake git submodule. Then pull once in a while.

Running Rails as an embedded app inside of a gem

I'm trying to understand what exactly the above (in my question's Title) means? This is taken directly from the SpreeCommerce.com project:
If you’re an experienced Rails developer you may be wondering where your app directory is. Spree actually runs as an embedded Rails app inside of your gem. How do you customize things then? We’ll cover that later in extensions.
Source: http://spreecommerce.com/documentation/getting_started.html
Can someone further explain what exactly it means when a Rails app is run "inside of your gem"
With the gem spree, you can install your application and use it. A lot of application need download complete package to install it. When the gem spree, you don't. So it's more easier to install spree on your server.
The phrase you quote is poorly written and not particularly useful. What you should take away is that Spree is structured different from the majority of Rails plugins.
Typical plugin:
your rails app <-- plugin functionality
A Spree app:
spree rails app <-- your site specific code
Typically, most Rails plugins are installed in the vendor/plugins directory of your Rails app. Some additional functionality is added by classes and modules that you can then reference in your code (subclassing a ResourceController, for instance).
Spree does not work in this way. Because, presumably, there is so much configuration code for Spree, each Spree instance creates a separate Rails app -- one that's missing some of the more important parts of a Rails app (such as the app directory). All of your site specific code goes in the vendor/extensions/site directory. This means you don't have to worry about editing any of the Spree-specific code (since it's all in a different directory) and you can more easily put your own code under source control.

Resources