Rails Engine gem using another Rails engine gem from git - ruby-on-rails

Rails 4 # Ruby 2
So i have two engine (A, B) gems that cannot be uploaded to Rubgems because the code is private, so im using git.
A must use B, so basically i should add B as a dependency in A gemspec. As far as i know, gemspec doesn't allow git based gems as a dependency inside gemspec.
I tried to use A gemfile but no luck. Is there a way out?

For development or test, you can do it in Gemfile. You can even point it to use your local folder.
gem 'gem_b', path: "/path/to/the/folder"
or to use a git reference
gem 'gem_b', git: "git#github.com:user/gem_b.git"
This will allow you to do the development and testing.
Another option is this. If you have 2 engines, I assume you also have a Rails app to use them. In that rails app, you can simply require them in Gemfile one after another using git reference.
gem 'gem_b', git: "git#github.com:user/gem_b.git"
gem 'gem_a', git: "git#github.com:user/gem_a.git"
If you must declare this dependency in gemspec, you can build the gem using rake;
cd /path/to/gem_b
rake build
This will create a gem_b.gem file under pgk folder.
Then you can install it in your local using gem instal like this
gem install pgk/gem_b.gem
Now you have gem_b installed in our local. There will be no problem adding it as a dependency in gemspec.
When you are ready to release your application, you need to copy gem_b.gem to your server and install using usual way;
gem install /full/path/to/gem_b.gem

Related

Developing Multiple Rails Plugins with Dependencies

I'm starting to build a series of plugins and engines in a project I'm developing and I've run into the issue of having to list the paths to dependencies in all of the Gemfiles for the main application and the plugins/engines if I want rake to work.
Rake works fine for the main application because it's Gemfile lists the relative paths to the plugins/engines I want, but when a plugin/engine is dependent on another and does not have the relative paths all listed, using rake rdoc I'll get an error like the following (presumably I'll get the same error trying to run tests/the dummy application/etc):
Bundler could not find compatible versions for gem "user":
In Gemfile:
auth (>= 0) ruby depends on
user (>= 0) ruby
Could not find gem 'user (>= 0) ruby', which is required by gem 'auth (>= 0) ruby', in any of the sources.
Rather than having to use paths, I've tried specifying the git repository in the plugins/engines like so:
# User engine
gem 'user', git: 'https://localhost/git/project/user.git', branch: 'master'
And then using bundler config local.user /path/to/local/repo command to make it point to a local repository for development. This appeared to work perfectly... until I change the version of the plugin in the local repo, then it spits out this error in any dependent plugin/engine/application:
Could not find user-0.0.1 in any of the sources
Run `bundle install` to install missing gems.
Whilst that isn't really much of an issue-- the version number will be changed at the end anyway --it also turns out that it will throw the following error if you're on a branch in the local repo instead of master:
Local override for user at /path/to/local/repo is using branch deleteme but Gemfile specifies master
And omitting the branch option from the Gemfile leaves me with this error:
Cannot use local override for user at /path/to/local/repo because :branch is not specified in Gemfile. Specify a branch or use `bundle config --delete` to remove the local override
So am I just stuck with having , path: "../local-repo-directory" strewn about all of the Gemfiles for plugins/engines with dependencies on one another whilst in development or is there a way of developing multiple interdependent plugins/engines for Rails at the same time that doesn't use a really sloppy/inelegant solution?
I'm drawing blanks on other ways to do this, so any help would be greatly appreciated. I hope I've explained this well enough, but if there's anything else I can clarify, let me know.
Thanks!
Stick with specifying git repositories in your Gemfile and using bundle local overrides to work on them.
Possible problems with solutions:
1. Local override for user at /path/to/local/repo is using branch deleteme but Gemfile specifies master
If your Gemfile specifies branch "master" then the local override should have branch "master" checked out. This is because the goal of a local override is so that you can work on a gem in a local folder while running and testing the application. In production it will check out the branch and revision specified in the Gemfile and Gemfile.lock and it should offcourse be exactly what you are running with your local override.
2. Could not find user-0.0.1 in any of the sources
Run `bundle install` to install missing gems.
When you run bundle install it places a version number for each gem in the Gemfile.lock. This file is added to git so that other developers and your production server runs the same versions of the gems as you do. Your Gemfile.lock needs to specify the same version of your gem as what is returned in the local override gemspec file. If you incremented the version number in the local override you need to run "bundle update gemname" in the application that uses it so that it updates the Gemfile.lock. Note that bundler caches everything in a gemspec file until you increment the version. Thus you can't add new dependencies or change dependency versions in a gemspec if you don't increase the version number in that gemspec.
The git-bundle gem
If you use a git repository in your Gemfile with local overrides bundler will store git revision hashes in your Gemfile.lock as mentioned above. Example:
Gemfile:
gem 'example', git: 'https://github.com/your_name/example.git', branch: :master
Bundle config shell command:
bundle config local.example /path/to/local/git/repository
Gemfile.lock (auto generated):
GIT
remote: https://github.com/your_name/example.git
revision: b9270e61abb89e1ff77fb8cfacb463e4d04388ad
branch: master
After you commit in the local override repository you will need to run bundle install on your main application so that it rebuilds the Gemfile.lock to include the new revision hash and commit it. I recommend using the gem below as it automates this process for you and also aids in other scenarios. See the gem page for exact detail.
https://github.com/EPI-USE-Labs/git-bundle
The activesupport-decorators gem
As a sidenote, when you need to extend classes between your gems you can use the decorator pattern which is implemented elegantly by the activesupport-decorators gem:
https://github.com/EPI-USE-Labs/activesupport-decorators

How to rename ruby gem after build is made?

I am trying to push into rubygems.orge a simple gem following this tutorial. Basically I am using bundler and I have write a simple Hello World class. Then, I try to push the gem as follows:
bundle gem my_first_gem
gem build my_first_gem-0.0.1.gem
and I get:
Signed in.
Pushing gem to https://rubygems.org...
Repushing of gem versions is not allowed.
Please use `gem yank` to remove bad gem releases.
So, I have checked and there is already a gem with such name. So, is there an easy way to rename the gem I have including changing the gem name in all generate by bulder files:
or if I should rename the files by hand, could you tell which are the critical ones?
Instead of renaming files by hand. As it is just a tutorial gem, I would suggest you to create a new gem with
bundle gem gotqn_first_gem
and just move your HelloWorld class in lib. And follow the rest of the commands suggested in Railscasts.
Don't forget that after renaming you need to call git add -A to update your files list.
The reason for that is because (unless that you have changed) your my_first_gem.gemspec have a line like that:
spec.files = `git ls-files -z`.split("\x0")
So, when you call gem build my_first_gem-0.0.1.gem, the above command will search for your older files and ignore the renamed ones.

Use gem as library in Rails 4

Is there a way to use a gem as a library in Rails 4?
I have tried putting in a gem folder after cloning into lib folder but this doesn't seem to be working
You can set local path to gem in your Gemfile if I clearly understood the problem.
# Gemfile
gem 'my_perfect_gem', path: './path/to/my_perfect_gem'
I think it's better to set local gem location only in development and test environments, so wrap this line in a group. Unfortunately you should restart your rails server any time you've updated the gem.
May be there is a better approach such as using your gem as a part of application in lib folder – Auto-loading lib files in Rails 4

Where are the gem files located?

Where are the gem files located ?
I'm new to rails and trying o understand how the whole gem functionality works.
My question is how can i follow a gem installation in order to confirm a gem is been installed ?
Where are the installed files located ?
From within your rails app, you can list out all of the gems being used, their versions, and the local path:
bundle show --paths
There's no reason to modify any of these files though. Configuration is typically done through an initializer in /app/initializers, but it depends on the gem being used.
If you need to modify something about the gem, you should fork it on Github and then reference the git location in your Gemfile until your pull request makes it back into the gem:
gem 'some_gem', '4.1.1', git: 'https://github.com/some_github_repo/some_gem.git'

Whats the best way to tweak ruby gems for code reading

To help understand the source code of various gems I often want to place various puts statements in the source code or even try using the ruby debugger.
But whats the best way of doing this?
Do you clone the project from github and make changes locally, if so how do you "force" the use of the local cloned code over the local gem on your machine. Do I just create some scripts that explicitly require the path of the cloned repos folder?
Or do should I use rvm to create a temp gemset, download the gem and modify it directly?
Are there any other methods ive overlooked? How would this change for gems designed for use within rails projects.
The way I usually do it when I want to make changes to a Gem:
Fork the repository on Github
Check it out and create a new branch for local changes
Use Bundler to manage dependencies for the project which uses the Gem
Change one line in the Gemfile to make it use the forked version of the Gem:
gem "thegem", :git => "git://github.com/name/thegem.git", :branch => 'mybranch'
or
gem "thegem", :git => "file:///path/to/thegem", :branch => 'mybranch'
with /path/to/thegem being the path to your local working copy.
The advantage is that you now already have a the perfect infrastructure set up for contributing your changes through a pull request :)
With Bundler.
In a Rails app simply edit the Gemfile and add:
gem "gem_name", :path => "~/MyGems/gem_name"
PS: Bundler work with any Ruby project.
You can use rvm to create a temp gemset, download the gem and modify it directly. A fast way to view/modify a gem is using gemedit :
Install:
gem install gemedit
Usage:
gem edit devise
or: gem edit devise -e mate

Resources