Ruby on Rails: Best way to add gems at project initialization - ruby-on-rails

Every month or so I have to create a Rails project at work.
The procedure is always the same...
Run rails new [...] & edit the Gemfile.
I have about 12 gems I always add on any project no matter what kind of project that is. Most of them are development gems, some of them production gems.
The gems range from ActiveAdmin to BetterErrors and so on. Problem is: I always have to remember which gems I use on a regular basis and run the same procedure everytime I start a project:
Open google.com
Search for the correct names of the gems
Add the gems to the Gemfile accordingly
Repeat til I'm satisfied with my Gemfile
I wish I could do something like this: rails new Project --use-my-gems
I know it's possible somehow using a text-file to store my most used gems (or a Gemfile itself and overwrite the default Gemfile with my).
Basically I want multiple Rails Gemtemplates which can be switched at project initialization by passing an argument to rails.

Use Rails Templates.
You can specify your gems in the template:
gem "bj"
gem "nokogiri"
... with a lot of other options.
Then start your new app with:
rails new app -m ~/template.rb

Related

How to use gems locally?

I would like to use gems 'better_errors' and 'binding_of_caller' for my debugging in rails app, but i DON'T want to include those in Gemfile. Is it possible to do? My first thought was to simply
gem install better_errors
gem install binding_of_caller
but it doesnt work, i mean installation finishes without problems, but thats it, gem doesnt seem to work at all when i run my app on localhost. Do I need some kind of config set, anybody?
but i DON'T want to include those in Gemfile. Is it possible to do?
Yes, it is possible. You can just download the respective directories in desire folder (ex. lib) and add that gem class in your initializer so it will be loaded at the time of starting. Configuration varies as per gem.
My first thought was to simply .... but it doesnt work,
Ofcourse, it wont. How can your rails app magically detects without knowing it that you have better way to show error. It is simply saying like you have cancer formula and doctors automatically applied that formula to there patient without you telling them. There should be some commucaition between two parties rails-app and gem so they can coordinate and work better.
Do I need some kind of config set, anybody?
Yes, explained above.
i dont want to force those gems on my coworkers. KRUKUSA any more details? // said in comment
Yes, including this gems in your rails app can do this job. This extension will be available automatically to your worked. (no force applied :P)
it looks like all you want to not show those gems to other co-worker, if so, you can use this trick with git.
To achieve this thing, first simply add the gems in your gemfile, run bundle and then make it untrackable with git. You can put Gemfile and Gemfile.lock in your .gitignore file. or you can add the first add the gems and mark it ignore with below command. Read more here
git update-index --assume-unchanged Gemfile Gemfile.lock
Another possibility would be to create your own environment and use it accordingly.
Have your own configuration for myenv:
$ cp config/environments/{development,myenv}.rb
In config/database.yml, add the environment myenv and use the same config as development:
development: &development
<rest of the code you have on config/databases.yml>
...
myenv:
<< *development
In Gemfile add your custom gems to use on your mydev group:
group :myenv do
gem 'better_errors'
gem 'binder_of_caller'
end
Run rails and rake with RAILS_ENV like this: RAILS_ENV=myenv rails c
The advantage of this approach is that you still get the updates from Gemfile from the repo, and if you need to add a gem in the Gemfile for everybody to see, you still can.
Also, nobody will see the gems you installed inside the myenv group in your Gemfile.

rails why need other project bundle gems?

i have two project,which one called A with Rails another called B just pure Ruby code.
when i call A controller actions named do_action it will call B rake tasks such rake dosomething
but i got error:
rake aborted!
cannot load such file -- pry
the gem pry in B Gemfile.
i want to know why rails project A will need B Gemfiles gems?
i think my linux env probelem? thk
Since you have call to rake dosomething to other's project from the specific (first) one, the environment gems will be applied from the first project. So, either:
add the pry gem dependency into the first project
generate the second project, which is in pure ruby, as a gem, and add it as a dependency into Gemfile of your Rails project as follows:
gem 'your_ruby_project_gem', :path => 'path/to/your/ruby/gem/project'
The way is for the projects, which are current under a development, i.e. the argument :path allows you to change the code under that path, so you gem will be also changed without reinstallation. Refer to more the bundler documentation. To run the Rails project you have to exec as follows:
bundle exec rails s
I prefer the second approach.

rails plugin vs bundle gem

This two commands seem to generate practically the same thing
rails plugin new __name__
bundle gem __name__
There is a hidden detail I haven't notice?
which one do you use, and basically, why?
Thanks
They can all generate a barebone gem but they are different.
rails plugin new could generate a dummy app inside test, and a basic test_helper, which would be very handy if you want to add some functional/integration tests in gem. You can also revise that a bit to use Rspec. bundle gem would not do that.
If you develop the gem for Rails and need such tests, rails plugin would be better. Otherwise bundle or a gem generating gem jeweller.
Plugins are more or less deprecated in favor of gems in recent versions of Rails.
As far as I can tell, running rails plugin my_gem simply creates a 'my_gem' directory in the root of your rails app.
It's not too much different from running bundle gem my_gem except that it stubs out a couple of test files, and runs bundle install.
This may be useful if you're creating a gem that's made to be run on rails - where you need a "rails environment" (see the test/dummy/app directory).
Still, if you do it this way, it appears the gem is added right into the root of your rails project. You could always move it, but if you were to run bundle gem you could do so wherever you want.

Rails locations - where do I locate a gem

In Rails -
Where should I locate Gems? I downloaded bootstrap and it's working, as well as a sample Rails app, separately, but I want them to work together. There is a bootstrapped rails gem (http://rubygems.org/gems/bootstrapped-rails) which I downloaded, but I'm unsure as to where I should locate it. Under models?
And how do I make sure I am referring to it? I need to add something in controller as well?
Again, more an answer to the question in the title than to what was intended by the questioner but you can use
bundle show <gemname>
To locate the directory where a gem is installed.
As Dfr mentioned: https://github.com/seyhunak/twitter-bootstrap-rails
Twitter bootstrap isn't anything more than (mostly) a collection of css/js/image files.
Add this to your gemfile
gem "twitter-bootstrap-rails"
run
bundle install
run for simple css
rails generate bootstrap:install static
It should place relevant js and css files into your application.js and application.css files accordingly. (Read more about asset pipeline)
To get you started, in the gem's link under section - "Generating layouts and views", you can see rake tasks to generate sample layouts.
e.g.
rails g bootstrap:layout application fixed
You should now have a twitter-bootstraped application.html.erb file under views/layouts.
To answer the question in the title, you can locate your gems by running gem env in the console. That will give you the specific information about your "RubyGems Environment:" When you run gem install some_gem_name it will add this gem to your system.
However, what it sounds like your trying to do is add a gem to your app. If this is the case you add gems to a rails application's Gemfile.
So using your example, you'd locate your Gemfile and add the following:
gem "bootstrapped-rails", "~> 2.0.8.5"
Once that's done, you run bundle install in your terminal.
I find that a good resource for basic rails information can be found here: http://guides.rubyonrails.org/getting_started.html
The tutorial is short and it will give you a great starting point.

Strategies for gem tests to ensure the gem works with Rails 3.x and 4.0?

I've seen a few examples of dummy Rails apps (for testing, so they live under test or spec dirs, typically) for use with the Appraisals gem that supposedly work with both Rails 3.x and Rails 4, but they seem hackish and not fully functional. It is somewhat expected, as it is a stripped down Frankenstein monster that is trying to be compatible with various versions of Rails 3 as well as Rails 4.
I've referred to projects that attempt to do this sort of testing (as of late March 2013) like less-rails and ember-rails, but this way to test with various version of Rails doesn't seem very clean, and it is non-trivial to try to debug a non-standard Rails application, especially in a beta version of Rails.
It would be great to have a cleaner way to test that allows you to have a full Rails application for each version of Rails to test with that through some magic is not that difficult to setup or maintain and don't require non-standard path hacks in places, etc.
What are the available strategies for testing gems with various versions of Rails (including at least latest Rails 3.1.x, 3.2.x, and 4.0.0.beta1), and what are the pros and cons of each?
A few options from the related thread on the rails-core list:
Option 1: Appraisal gem and single Rails dummy app
Ken Collins mentioned using appraisal and a Rails "dummy" app:
I test minitest-spec-rails against 3.0, 3.1, 3,2 and 4.0 using a mix
of appraisal and dummy_app that minimally configures itself depending
which rails version it is testing against. Some links:
https://github.com/metaskills/minitest-spec-rails
https://github.com/metaskills/minitest-spec-rails/blob/master/test/dummy_app/init.rb
Similar techniques are used in less-rails, ember-rails, and high_voltage among others.
I used a similar setup to high_voltage in restful_json (v3.3.0) but with a full Rails app created with 4.0.0-beta1 that I modified minimally to also work with Rails 3.1.x/3.2.x.
Update: May want to see permitters for more recent example.
Pros: Fairly simple. Can test against various Rails versions from command-line, etc. Can be very minimal Rails app configuration, or can use full Rails app with minor differences.
Cons: Still reusing same Rails app for multiple Rails versions, so some conditionals and unneeded config. (Possible issues with some files not being applicable in another version of Rails, etc. but does not appear to be a big problem.)
Option 2: Rails version as environment variable with single Gemfile, single Rails dummy app, relying on travis-ci to test in multiple versions
Steve Klabnik mentioned a solution that works with a single Gemfile, a single full Rails app (even though under "dummy" dir, and no use of the appraisal gem, by relying on travis-ci to test:
I've been meaning to discuss this topic more, as I've been doing it
for a bunch of my gems lately. I have two that do this:
Draper: https://github.com/drapergem/draper
LocaleSetter: https://github.com/jcasimir/locale_setter/
Basically, I embed an entire Rails application into the gem, and then
run it against multiple versions of Rails on travis via env vars.
Pros: Simple. No dependency on appraisal gem (not that it is a problem, but may be easier to maintain).
Cons: Still reusing same Rails app for multiple Rails versions from what I can tell. Unless using travis-ci or something that starts with a clean gemset (i.e. if running at command-line), not currently differentiating gemsets so newer gem may be used with older Rails, etc., but Steve said if that were to cause a problem, you could just blow away the lock and re-bundle.
There's a third option : using multiple gemfiles and multiple dummy apps.
Gemfiles
Bundler has an useful option named --gemfile. With it, you can specify what file to use instead of Gemfile, and it will generate a lock file after the same name :
bundle install --gemfile Gemfile.rails3
bundle install --gemfile Gemfile.rails4
This will generate Gemfile.rails3.lock and Gemfile.rails4.lock. So, those Gemfiles can be a copy of your main Gemfile forcing rails version :
source "http://rubygems.org"
gemspec
gem "jquery-rails"
gem "rails", '~>4'
Using gemfiles from dummy apps
Then you have two dummy apps, one for rails-3 and one for rails-4. To use their proper gemfile while running (for example) migrations :
cd test/dummy_rails3
BUNDLE_GEMFILE=../../Gemfile.rails3 bundle exec rake db:migrate
cd ../dummy_rails4
BUNDLE_GEMFILE=../../Gemfile.rails4 bundle exec rake db:migrate
Yeah, that's probably the worst part. But this is mostly a one time setup.
Using gemfiles from rake
To instruct which version to use while running tests, set the environment variable BUNDLE_GEMFILE in Rakefile :
#!/usr/bin/env rake
rails_version = ENV[ 'RAILS_VERSION' ] || '4'
if rails_version == '3'
ENV[ 'BUNDLE_GEMFILE' ] = 'Gemfile.rails3'
else
ENV[ 'BUNDLE_GEMFILE' ] = 'Gemfile.rails4'
end
begin
require 'bundler/setup'
rescue LoadError
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
end
I prefer to ask the user to pass RAILS_VERSION instead of directly BUNDLE_GEMFILE because it's easier to remember and we can just pass "3" or "4".
Using correct dummy app from tests
Finally, in test_helper, switch the dummy app depending on what rails version has been asked for :
# Configure Rails Environment
ENV["RAILS_ENV"] = "test"
dummy_app = ENV[ 'RAILS_VERSION' ] == '3' ? 'dummy_rails3' : 'dummy_rails4'
require File.expand_path("../#{dummy_app}/config/environment.rb", __FILE__)
require "rails/test_help"
From your user perspective
For your user to run tests, he will have to do a one time setup by running the migration tasks with BUNDLE_GEMFILE, which is not that sexy.
But once done, user can run tests against rails-3 and rails-4 without the need to generate the Gemfile each time he wants to switch version, and you can have version specific code and configuration within your test apps without having to put if Rails.version >= '4' statements everywhere.
To run specs :
RAILS_VERSION=3 bundle exec rake test
bundle exec rake test # rails-4 is the default in code I wrote
You can see an example for this method in my activerecord_any_of gem.

Resources