Rails: vendor/gems or vendor/plugins? - ruby-on-rails

I'm to tracking dependencies with git-submodules in my rails app. So far I've added submodules for things like, haml, shoulda, and authlogic to 'vendor/plugins'. I've seen indications that I should be using 'vendor/gems' instead though.
Question: which directory is the appropriate place to put dependencies being tracked as submodules? Is the choice arbitrary?
Thanks

In short, I'd use config.gems for everything except for the exceptions I've noted below.
This is the workflow I'd use:
All plugins/libraries for which gems exist for the version I need, I do
environment.rb
config.gem "plugin_name", :version => ">=1.0.0"
then:
rake gems:unpack:dependencies
All other plugins that I install from source (Github, etc.) I run:
script/plugin install github_url
and the plugin is placed in vendor plugins.
As far as submodules go, I'd only use submodules for plugins/gems that I'm actively developing or for which I plan to use specific commits, rather than the HEAD, and if I plan to change the commit I'm using often.

The short version - if it's a plugin put it into vendor/plugins, if it's a gem it goes to vendor/gems. However, there's no need to track gem dependencies via submodules - Rails config is just good enough for that. So, the usual pattern is this: use config.gem for gem dependencies tracking and git-submodules for plugin dependencies - and plugins always go to vendor/plugins.

Related

using devise WITHOUT the gem, can I simply copy the files?

Could I simply copy the devise app and lib (and gem?) folders into my respective project folders and have them work just as if I was using the gem? I'd like to do this so that I can really see all the code, possibly do some customization, and also avoid some "cannot find" errors in my IDE.
Is this a bad idea? If this is something that would work would I simply need to remove the gem and copy over the necessary files or would I need to "undo" things that the gem has done. Could this create problems down the road with updates?
Lastly, how exactly is devise working when I do not have all of the code in my project? It works when I'm offline so is the code just stored in some secret invisible file or something? Do some gems require an internet connection to retrieve their functionality or could any gem simply be copied and used in a project without declaring it in the gem file.
See http://bundler.io/v1.5/git.html
Bundler also allows you to work against a git repository locally instead of using the remote version. This can be achieved by setting up a local override:
bundle config local.GEM_NAME /path/to/local/git/repository
Also
http://ryanbigg.com/2013/08/bundler-local-paths/
"There's a little known feature of Bundler that allows you to use a local Git repository while developing locally, and a remote Git repo when deploying. This feature means that you no longer have to constantly switch between local paths:"
gem 'spree', :path => "~/Projects/gems/spree"
And remote paths:
gem 'spree', :github => 'spree/spree', :branch => 'master'
Whether this is possible, short answer: Yes. Is this a bad idea? Definitely! In fact, the code is not in your project, but when you install a gem, all its contents will be stored somewhere in your local machine. Therefore, once downloaded, you don't have to be online to use it. Well, though it's not common (and not recommended), you can clone the gem's repository to your project and set the path in the project's Gemfile.

What's the best way to edit and test an existing Ruby gem, namely Gollum?

I'm starting a project where I will work with the base Gollum wiki gem, and add some features to it. I was wondering what is the best way to do this.
Do I need to build and install the gem everytime I need to test it? Is there a way to edit the source code of the gem and test it on-the-fly?
I'm only a beginner at this, so sorry if this is a silly question!
Clone the git into your userspace;
Checkout the source code somewhere into your Projects directory;
Put in your main projects Gemfile the following:
(instead of :git => ...)
# V VERSION IS HERE
gem 'gollum', '~> XXX', :path => '/home/Projects/gollum'
Run bundle update in your main project directory each time you changed smth in gollum. Don’t forget to commit changes to github into your gollum fork and point gem instruction to it into Gemfile before uploading.
Hope it helps.
There a couple different things you can do in this situation if you are using bundler. First, you could simply edit the gem locally. Running bundle show gollum will show you the directory in which the gem is installed and you can simply edit it and the changes will appear in your application. In the end, you will need to either fork the gem and use your own version in your Gemfile. Documentation on using a custom git repository can be found here: http://bundler.io/git.html
Also in that documentation is how to set up a local git repository. If you plan on having a separate gollum repository and pushing it our, you will probably want to work with a local copy. Rather than simply pointing to a separate directory on the filesystem, it is useful to use bundler's "Local Git Repos" feature, which is also documented in the link above.
Either way, once you are ready to push out your code, you will want to point your code to the remote repository so you can actually deploy it.

Managing Gemfile.lock with gems bundled from same repository

Here's the situation. I work on a large Rails 3.2.13 app (Ruby 1.9.3, Bundler 1.3.5). We've recently begun the process of making this app less monolithic by breaking some components out into gems/engines. However, we have kept the source code in the same git repository. So we've got a file structure like:
APPNAME
|-app
|-gems
|---engine1
|---engine2
|-lib
etc.
Then the Gemfile looks like:
gem 'engine1', :path => File.expand_path('../gems/engine1', __FILE__)
gem 'engine2', :path => File.expand_path('../gems/engine1', __FILE__)
So far so good. My problem is that Gemfile.lock is no longer consistent between developers. Whenever I fetch changes from source control and run rspec or rails server or whatever, I get a modified Gemfile.lock where the diff looks like:
PATH
- remote: /Users/OTHER_DEVELOPER/PATH_TO_APP_SOURCE/gems/engine1
+ remote: /Users/ME/APPNAME/gems/engine1
We've always followed what we considered to be the best practice of checking our Gemfile.lock into source control, but now that's causing git headaches. Has anyone dealt with this problem before? Any ideas for a solution?
The problem here is that you're using gems in an unintended way. They are gems, not DLLs.
If you want a gem approach, host them on a private server and refer to that server in your GEMFILE.
If you want a DLL-like approach in ruby, just use a folder for each library.

How to get an application to use a local branch version of Ruby on Rails

Let's say I want to add some new features to Rails. According to the Rails Guide on how to contribute to Rails, I should clone the main repository, create a branch, then make my changes in that branch.
My question is: after I've done all of that, how do I go about testing my changes in an actual Rails application? That is, how do I get a Rails application running on my machine to use the Rails code from my branch rather than the Rails code installed on my system?
The simplest approach I can think of is to simply replace the "rails" folder in my gems folder with the code from my branch, but it seems like there should be a cleaner way to do this.
If you're using bundler, just point to your modified version in your Gemfile by specifying either the path of the gem on the filesystem or your forked git repo. Like this:
gem 'rails', :path => '/full/path/to/mofidied/rails'
or for git:
gem 'rails', :git => git://github.com/github_user/your_rails.git
If you change the minor revision number and install it in your gems folder you can specify that new version when you create a new app
rails _3.0.x_ new newappname

How can I modify Rails' config within an engine plugin?

I'm working on an engine for Rails as a plugin. I'd like it to be able to make necessary changes to Rails' configuration when it's loaded so it can specify its Gem dependencies as well as add some load paths.
The plugin's init.rb file has access to the config object but this is effectively read-only, you can specify a gem but it makes no difference, the initializer must have run already at this point.
I've got around this for now by requiring a file with a new Rails::Initializer block like so:
Rails::Initializer.run do |config|
config.gem "authlogic", :version => ">= 2.0.9"
# etc
end
This works but wipes out any existing configuration in the main application's environment.rb.
Maybe I can solve this by having a generator in the engine that adds something to environment.rb that loads the plugin's config at the right stage, or maybe there is a way of adding a file to config/initializers to do this job. Not sure how best to go about this though.
I would go with the config/initializers route. That is the standard folder to put plugin-specific config code and it will get loaded at the correct time.
For implementation, I would try my hardest to choose sensible defaults for everything that allowed me to not have a config file. (I understand this is not always possible.)
Next I would create a generator with the plugin that would automatically create the config file in config/initializers using:
./script/generate plugin MyPlugin --with-generator
Finally, I would put something in install.rb of my plugin to run the generator script when the plugin is installed. This way the config file is generated automatically with the install, and the user still has an easy way to regenerate if he wants to restore the default configuration.
Are you sure you want to distribute this as a plugin rather than a gem? If you package your engine as a gem then you can specify gem dependencies as part of your gem build process. For example, if you use Jeweler to create your gem you just add a single line:
s.add_dependency 'authlogic'
When your gem is installed it will make sure all dependencies are installed. Google 'jeweler gem dependency' for a full Jeweler config example.
Also, I've been doing a lot of work on my own rails engine and recently extracted a lot of useful base functionality. You may find this helpful for other engine issues:
http://keithschacht.com/creating-a-rails-3-engine-plugin-gem/
You can easily add this line to init.rb (under your plugin directory)
config.gem 'quick_magick'
I tried it with rails 2.3.5 and it worked like magic.

Resources