Deploying an app with engine using git and local versions - ruby-on-rails

I am trying to understand the workflow for deploying a rails engine. I read this answer. But I don't fully understand what is going on between Gemfile, bundler, Capistrano and rails.
I have a situation where I am working on an app locally pushing to a git repository and using Capistrano to deploy. In my apps Gemfile
#gem 'my_engine', git: "git#myrepo.com/myengine.git"
gem 'my_engine', path: '/local/path/to/MyEngine'
When I am developing I often comment out the git repository and use my local( I know some may take issue with this but another time another question) what I want to know is:
when is the engine included or mounted?
If I am working with the local engine and decide to deploy the app is the local engine included at this point?
Would the local current branch/state be what is used?
If I decide to switch to the repo for production(and or dev) at what point is that included?
Does Capistrano run bundle install during the deployment?
Would Capistrano be able to use my local copy or would it need me to use the git repo?

Engine and Host application are in same repository then specifying
gem 'my_engine', path: '/local/path/to/MyEngine'
will work.
If you had different repository for engine and application then need specify gem as
gem 'my_engine', git: 'git#github.com:my_engine.git',
branch: 'master', revision: 'cb1a8d2495168d411676f58bdfc9015fe728948c'
branch and revision are optional but its recommended if you want to point it to specific commit or branch.
Make sure the deploy(user on server used to deploy application) user has access to engine repository.

Related

Rails deploying Gemfile.lock to development and production repositories

I have a single app directory for development: d:/some/dir/myapp. I have a single repository called sample-repo, but it has two branches: develop and master.
My app's Gemfile uses the sample-repo repository's environment-specific branch:
RAILS_ENV = ENV['RAILS_ENV'] || 'development'
gem 'sample-repo', git: "git#bitbucket.org:MyUserName/sample-repo.git",
branch: "#{ RAILS_ENV.to_sym == :production ? :master : :develop }"
My web host has two separate directories; one for development and the other for production. Each are updated via a git pull from their respective branches (development => develop, production => master).
This is a problem because when I run bundle update on my development machine, the Gemfile.lock contains the sample-repo gem, specifying the develop branch. I then git push the Gemfile.lock to my repo (both develop and master), and now the master repo contains a Gemfile.lock that specifies the develop branch!
i.e., the problem is that there is only one Gemfile.lock file to go around between the develop and master branches.
This answer solved my problem. I created a file called .rails-env which contains a simple string specifying the environment bundler should use. This file must be kept out of the repository. If not present, bundler defaults to development.
The second part of the problem was that I had to adjust my deployment procedure. I created a small script that runs bundle update under the development environment and waits for a key press before doing the same for production. Once the development Gemfile.lock files are generated, I push the changes to my develop repository branches. After it runs through production, I push to master.

Mounting a Rails engine in a Heroku app

I have two projects that are version controlled in their own respective private GitHub repositories.
One of them is a Rails app, and the other one is a Rails engine.
I do not want to expose the Rails engine as a public gem.
How can I declare my Rails app has a dependency on the engine in such a way that Heroku can resolve it?
You can use a private gem server like Gemfury. It is also a Heroku addon (free plan works fine for your case).
This way you'll be able to release versions of your gem. Works much like rubygems, but is private.
Assuming that your engine is a gem in a private Github repository, you can try this approach, which uses an OAuth token:
https://gist.github.com/masonforest/4048732
As noted in the comments, the version which involves hardcoding the OAuth token value in your Gemfile is less secure than using an environment variable.
You can vendor your engine by placing the source in the vendor folder, then in your Gemfile reference it by path:
# Gemfile
gem 'some_engine', path: 'vendor/some_engine'
Either directly copy-paste the source there, or use a Git submodule. Run bundle install and you should be set.

Convert a Rails Gem / Engine to an application

The rails engines feature is pretty good, and I have watched the Railcasts and read the Rails documentation on it. I can see how you can access or override all the relevant components in the engine.
However, say I wanted to drastically modify the engine's code, is it possible to convert the engine back into a normal Rails app, and then take it from there. Is there anything else involved other than copying the directories in the gem over an empty application directory?
I am looking at this engine:
https://github.com/ging/social_stream
Yeah you can, just go to https://github.com/rails/rails & hit the fork button to fork the repository to your github account (assuming you already have one setup). Afterwards, clone the forked project to your local machine with:
git clone your_forked_repository_url.git
If you don't feel the need to fork your own version run:
git clone git://github.com/rails/rails.git
At this point you can make modifications to your heart's content. To use a local copy of the gem in a rails application add the following to your Gemfile (replacing the old rails gem):
gem "rails", :path => "/somewhere/your_rails_project"
All of this and more is highlighted in http://edgeguides.rubyonrails.org/contributing_to_ruby_on_rails.html

Deploying a modified vendor asset to Heroku

I have Jquery-datatables-rails gem installed. When you install the gem via bundle a folder is created under .rvm/gems/RUBY#GEMSET/gems/jquery-datatables-rails
Inside of this folder you can browse to the vendor/assets folder and modify the CSS, etc.
The only problem is that upon deployment a remote version of the gem is installed on the remote production instance, which does not reflect the local changes.
Is there any way to ensure the local modifications are pushed to Heroku?
Thanks
You can fork the gem and point to it on github as you mentioned, or you can make the changes to your local assets directory which will speed up the time it takes to compile your app on Heroku.

Using Hunspell With Heroku

I'm building a Rails app that uses Hunspell and the hunspell-ffi gem so that Ruby can interface with it. I'm deploying the app to heroku, but unfortunately it needs Hunspell to be installed on the server in order for the gem to work.
Is there any way for me to install Hunspell on Heroku? Or am I going to have to migrate to EC2?
Thanks in advance :)
You need to build the required Hunspell library and include it in your Heroku project directly.
Heroku runs on 64-bit Ubuntu therefore the binary has to be compiled under that system. The best approach is to simply use Heroku's Vulcan build server to compile on a Heroku instance.
Compiling for Heroku
gem install vulcan
vulcan create vulcan-compile-me last argument is your own app name.
Download Hunspell source
Extract
vulcan build -v -s ./hunspell-1.3.2 Tells Vulcan to build it and downloads the finished product automatically to /tmp/hunspell..
The build server requires the cloudant add-on, this is installed automatically but you have to make sure to have a verified (credit card added) Heroku account. If you get errors in step six of no build output then do heroku addons:add cloudant --app vulcan-compile-me
Adding to Your Project
Extract the Heroku Vulcan build tar from /tmp
Copy the entire lib folder to vendor/hunspell in your project root directory
Tell Heroku where to look for libraries: heroku config:add LD_LIBRARY_PATH=vendor/hunspell/lib.
Install Dictionaries
Download some dictionaries from Open Office and add them to your project. A good location is a folder called dictionaries at root level. This path is then referenced when initializing Hunspell in Ruby.
http://extensions.services.openoffice.org/dictionary
ftp://sunsite.informatik.rwth-aachen.de/pub/mirror/OpenOffice/contrib/
Using
Install your favorite Hunspell gem, I use hunspell-ffi. There is a newer gem for Hunspell but I prefer the previous FFI gem. To use initialize the Hunspell object with your dictionaries folder path and language (language match the dictionary file name).
dict = Hunspell.new("dictionaries", "en_US")
if dict.check('caribean') == false
suggestions = dict.suggest('caribean')
if (suggestions.size)
correction = suggestions.first # returns 'caribbean'
end
end
Vendoring for More Complex Projects
You can also vendor the library into your project by putting the tar built by the Vulcan server in the first step into a public accessible server such as Google Storage and then changing the Heroku build pack to download the tar on each instance startup.
heroku config:set BUILDPACK_URL=https://github.com/peterkeen/heroku-buildpack-vendorbinaries.git
The vendor build pack looks for a .vendor_urls file at the root level with HTTP links to the tar balls to install (needs to end in a new line to work).
http://commondatastorage.googleapis.com/developer.you.com/hunspell-heroku-1.3.tgz
Vendoring unpacks the tar into the root folder so the lib path for the Heroku settings would then just be "lib". heroku config:add LD_LIBRARY_PATH=lib
Unless I am mistaken or something has changed (I cannot find any evidence of this), you cannot install external native libraries on Heroku. If the library is not already installed (this is the case, I think, for ImageMagick, and perhaps others), you will not be able to use the gem.
Checkout this url: http://gems-summary.heroku.com/2011-07-19
It's freaking amazing how much support Heroku has for the gem community. So all you need to to is add the gem to your bundle since Hunspell is on rubygems, bundle install, and then deploy.
Gemfile
source 'http://rubygems.org'
gem 'rails', '3.0.5'
gem 'hunspell'
Then add to git:
git add .
git commit -m 'added hunspell'
Then bundle:
bundle
And deploy:
git push heroku
With Bundler, you should be able to install any gem. According to http://devcenter.heroku.com/articles/how-do-i-install-gems-for-my-app, "Almost any gem - even those with native dependencies - can be installed using Bundler. If there’s a specific gem that won’t install on Heroku, please submit a support ticket."
AFAIK, when your app is spun up, gems in the Gemfile are installed on-the-fly to the server your app is spun up to.
The Aspen stack has pre-installed gems, but you still should be able to add gems not pre-installed.
The bamboo stack has no pre-installed gems, so all gem dependencies must be declared explicitly. I believe that is the same for the Celadon stack.

Resources