Including rake tasks in gems
On Rails 3, you do this via Railties. Here's the code to do it for a gem I just made:
class BackupTask < Rails::Railtie
rake_tasks do
Dir[File.join(File.dirname(__FILE__),'tasks/*.rake')].each { |f| load f }
end
end
So you basically create a class that inherits from Rails::Railtie
, then within that class you have a rake_tasks
block that loads the relevant files. You must load instead of require if you want to use a .rake
extension.
I found that I need to specify the full path to Dir
(hence the File.join
gymnastics). If I just wanted to list the file explicitly then I could get away with just saying load 'tasks/foo.rake'
because the /lib
dir of my gem was in the load path.
Requiring a gem inside a gem's rake task
Here is what I did to make it work:
tasks.rake
require 'database_cleaner'
require 'dummy_tasks'
namespace :db do
task :dummy => :environment do
DatabaseCleaner.strategy = :truncation
DatabaseCleaner.clean
Rake::Task['db:seed'].invoke
end
end
There may be a more elegant way to do this, but this should at least prevent you from having to add the database_cleaner gem to the app Gemfile
Running gems rake tasks from application rake tasks
so there are several things to be taken into consideration here.
for the record, this is how you call a task with arguments
Rake::Task["taskname"].execute(args)
in your case, i did not realize first, that it actually uses environment variables instead of task arguments that are read as ENV['CLASS']
.
that would answer your question, so you can either set it ENV['CLASS'] = 'ClassName'
or pass it along to your call to the rake task rake geolocal CLASS=ProposedAccomodation
.
which brings me to a following question: why are you not just calling the original rake task, there is nothing you add to it.
Local rake tasks require development gems to be in production group
Maybe not the most exciting answer but I just moved the require 'dev_gem'
inside the rake task
block for that task.
namespace :elasticbeanstalk do
desc 'Creates a new web & worker environment pair for testing'
task :create do
require 'aws-sdk-elasticbeanstalk'
# Do stuff with beanstalk that we wouldn't from a production env
end
end
This way the library only gets loaded when the rake task is invoked rather than when the rake task is defined.
Why is this gem not adding rake tasks to a Rails app?
The problem was not with the gem, but with the way it was included in the app.
In the Gemfile
, this works and includes the rake task:
gem 'gem_fresh'
This works but doesn't include the rake task:
group :development do
gem 'gem_fresh'
end
This seems to be due to how Bundler requires gems in Rails apps. From the documentation:
By default, a Rails generated app calls
Bundler.require(:default, Rails.env)
in your application.rb, which links the groups in your Gemfile to the Rails environment.
If for some reason that Rails.env
argument wasn't evaluating to include the :development
group, which seems to be the case when I call rake -T
, the gem wouldn't be Bundler.require
-d, and the rake tasks wouldn't be loaded.
The fact that it isn't including the :development
group seems to be an odd Bundler "gotcha", but at least now I know that moving it to the default group solves the issue and it's not a problem with the gem.
Ruby Rake load tasks from a gem
Okay, I found a solution for this problem if anyone is interested:
# Rails.root/Rakefile
spec = Gem::Specification.find_by_name 'test'
load "#{spec.gem_dir}/tasks/deploy.rake"
That's all I needed to say in my Rakefile!
Rake tasks inside gem not being found
Fixed it on my end. In the gemspec, you need to include the rake tasks files as well, not just the lib files:
Instead of:
s.files = Dir['lib/**/*.rb']
Use:
s.files = Dir['lib/**/*.rb'] + Dir['tasks/*.rake']
rails rake task with globally installed gem
If you do want to load a gem without having it in your Gemfile you can do the following in your rake task:
$: << '/Users/<user>/.rvm/rubies/ruby-
x.x.x/lib/ruby/gems/x.x.x/gems/smarter_csv-x.x.x/lib'
require 'smarter_csv'
I think the option to have the gem in your Gemfile with the require: false
option is more suitable however. The gem won't be loaded until you specifically require it.
Load rake tasks from ruby gem
I've just restarted spring and new rake tasks appeared in my rake -T
list. :)
Related Topics
How to Save Values into a Yaml File
Should One Use Dashes or Underscores When Naming a Gem with More Than One Word
Force Strings to Utf-8 from Any Encoding
Fast Way to Get Remote Image Dimensions
Write CSV in Ruby 1.9 and CSV::Writer
What Does :: (Double Colon) Mean in Ruby
Is It a Bad Practice to List Ruby Version in Both Gemfile and .Ruby-Version Dotfile
Nokogiri: Select Content Between Element a and B
Calculating Difference in Time Between Two Time Objects
How Does Rails Csrf Protection Work
When to Use a Lambda in Ruby on Rails
What Is '$:.Unshift File.Dirname(_File_)' Doing
Sprockets::Circulardependencyerror in Store#Index
What Is the %W "Thing" in Ruby
How to Get Attributes That Were Defined Through Attr_Reader or Attr_Accessor