I'm using Sinatra, and I wanted to set up some of the convenience rake tasks that Rails has, specifically rake db:seed.
My first pass was this:
namespace :db do
desc 'Load the seed data from db/seeds.rb'
task :seed do
seed_file = File.join(File.dirname(__FILE__), 'db', 'seeds.rb')
system("racksh < #{seed_file}")
end
end
racksh is a gem that mimics Rails' console. So I was just feeding the code in the seed file directly into it. It works, but it's obviously not ideal. What I'd like to do is create an environment task that allows commands to be run under the Sinanta app/environment, like so:
task :environment do
# what goes here?
end
task :seed => :environment do
seed_file = File.join(File.dirname(__FILE__), 'db', 'seeds.rb')
load(seed_file) if File.exist?(seed_file)
end
But what I can't figure out is how to set up the environment so the rake tasks can run under it. Any help would be much appreciated.
I've set up a Rakefile for Sinatra using a kind of Rails-like environment:
task :environment do
require File.expand_path(File.join(*%w[ config environment ]), File.dirname(__FILE__))
end
You then have something in config/environment.rb that contains what you need to start up your app properly. It might be something like:
require "rubygems"
require "bundler"
Bundler.setup
require 'sinatra'
Putting this set-up in a separate file avoids cluttering your Rakefile and can be used to launch your Sinatra app through config.ru if you use that:
require File.expand_path(File.join(*%w[ config environment ]), File.dirname(__FILE__))
run Sinatra::Application
Related
I have a path defined in my environment.rb file
MyRailsApp::Application.configure do
config.xml_import_path = "/path/to/xml"
end
I'd like to be able to set a variableaccess these within a Rake file like this
namespace :myapp do
xml_path = MyRailsApp::Application.config.xml_import_path
task :first_task => :environment do
# do some stuff with xml_path
end
task :second_task => :environment do
# do some other stuff with xml_path
end
end
but I keep getting an error when I run rake myapp:first_task
undefined method `xml_import_path' for #<Rails::Application::Configuration:0x00000006a98bd8>
I guess it's something to do with the environment no being loaded, as it works if I put
xml_path = MyRailsApp::Application.config.xml_import_path
inside the task definition.
Is there any way to use config values set in environment.rb like I am attempting to do?
Is there a better/right way to do it?
cheers,
Luke
Is there any way to use config values set in environment.rb like I am attempting to do?
yes you can load your Rails Environment into any script
just add
ENV['RAILS_ENV'] = ARGV.first || ENV['RAILS_ENV'] || 'development'
require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
before you call the variable you want to call
however, the best way to load the environment in your case is to add the above code to the bin/rake file or the config/boot.rb one
reference: https://shifteleven.com/articles/2006/10/08/loading-your-rails-environment-into-a-script/
Another way is to use the dotenv gem and save the path in the .env the file then load that var in your environment.rb and rake file
namespace :fixtures do
namespace :load do
task :prepare => :environment do
ENV['FIXTURES_PATH'] = "spec/fixtures"
ENV['RAILS_ENV'] ||= "test"
puts ENV.inspect
Rake::Task["db:fixtures:load"].invoke
end
end
end
I have added this to a special.rake file in ./lib/tasks in order to cause the rake db:fixtures:load command to apply to fixtures in the spec/fixtures directory, and to apply to the test environment.
It's not working. Where have I gone wrong?
You need to reconnect to the database. Something like
ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations["test"])
Changing ENV['RAILS_ENV'] after environment is already loaded doesn't do anything.
Perhaps it would also work if you load the environment task after you change ENV, but not sure about that:
task :prepare do
ENV['RAILS_ENV'] ||= "test"
Rake::Task["environment"].invoke
Rake::Task["db:fixtures:load"].invoke
end
I'm trying to test a rake task and it uses an active record in it.
require 'spec_helper'
require 'rake'
load File.join(Rails.root, 'lib', 'tasks', 'survey.rake')
describe "survey rake tasks" do
describe "survey:send_report" do
it "should send a report" do
Rake::Task['survey:send_report'].invoke
end
end
end
When I run this spec rspec spec/lib/survey_spec.rb, I get this error "
RuntimeError:
Don't know how to build task 'environment'
How do I load the :enviroment task inside by example spec?
I think you should first load the tasks:
require 'rake'
MyRailsApp::Application.load_tasks
and then invoke your task:
Rake::Task['survey:send_report'].invoke
I suspect the problem is that your survey:send_report task depends on :environment but you haven't loaded the file that defines the :environment task. That'll be in rails somewhere, and your main Rakefile loads it.
So, I think if you change
load File.join(Rails.root, 'lib', 'tasks', 'survey.rake')
to
load File.join(Rails.root, 'Rakefile')
it'll work.
Sounds like your take task may need the Rails environment to be loaded. You can stub this out by adding this line to your before(:all) hook:
Rake::Task.define_task(:environment)
Is your task adding the :enviroment to do it before? In your .rake file you should have something like this:
namespace :survey do
# ...
task :send_report => :enviroment do
# ... stuff
end
This is because you need to load the full enviroment to do that task. You can check this railcast to get more information http://railscasts.com/episodes/66-custom-rake-tasks
I'm using Rails3 (Windows, Ruby 1.8.7) with rufus-scheduler gem. Gem works fine, but if I'm trying to run some standard rake task, error occurs:
Don't know how to build task 'db:version' # ofc, db:version is just example
Terminal command
rake -T
works
If I'm trying to define own simple rake commands, they works fine too:
# /lib/my_scheduler.rb
require 'rubygems'
require 'rake'
require 'rufus/scheduler'
load File.join( Rails.root, 'lib', 'tasks', 'my_own_tasks.rake')
scheduler = Rufus::Scheduler.start_new
scheduler.every '5s' do
Rake::Task["my_own_namespace:test"].invoke
end
end
# /lib/tasks/my_own_tasks.rb
namespace :my_own_namespace do
task :test do
puts "Some scheduler task"
end
end
... but using standard rake tasks *in my_own_tasks* throws the same error.
Some help would be appreciated
PS. I'm newbie, so sorry, if that was dumb question
Maybe someone will need solution:
system("rake namespace:task")
f.e:
system("rake db:version")
(This is really a newbie question about Rake & Rails & dependencies in general. Trying to wrap my head around how all this fits together)
Basically, I want a Rake task that acts like seed.rb but is called separately. It adds test data for the development environment, while my seed.rb provides basic data for all environments.
The script, family_seed.rb, uses FactoryGirl to generate some records. It looks like this:
require File.expand_path('../../config/environment', __FILE__)
require './spec/factories'
Family.delete_all
Member.delete_all
zinsser = Factory.create(:family, :last_name=>'Zinsser', :first_name=>'Carl', :sim_id => '500')
blackburn = Factory.create(:family, :last_name=>'Blackburn', :first_name=>'Greg', :sim_id => '501')
It runs fine with bundle exec "ruby db/family_seeds.rb", but my question is how to set it up with Rake. Should the whole thing be placed inside a Rake task? How could I, instead, set up a task that would call the script, while ensuring that the Rails development environment is available when it runs? I'm trying not just to get the job done, but to do it in a "right" way.
One way to approach this would be to create a class or module in lib (this makes it easier to write tests for, and makes the code more reusable):
require '../spec/factories'
class FamilySeed
def self.seed
raise "Don't run this in production!" if Rails.env.production?
Family.delete_all
Member.delete_all
zinsser = Factory.create(:family, :last_name=>'Zinsser', :first_name=>'Carl', :sim_id => '500')
blackburn = Factory.create(:family, :last_name=>'Blackburn', :first_name=>'Greg', :sim_id => '501')
end
end
How to create the rake task:
require 'family_seed'
namespace :seed do
task :families => :environment do
FamilySeed.seed
end
end
I'd be careful with allowing things like Family.delete_all and Member.delete_all to be too freely used. You could easily shoot yourself in the foot later on by calling something you didn't mean to on a production db.
How to run the rake task:
Run it in your command like with the following:
bundle exec rake seed:families
Create a rake task and require :environment
task :delete_all => :environement do
require Rails.root.join('spec/factories')
Family.delete_all
Member.delete_all
zinsser = Factory.create(:family, :last_name=>'Zinsser', :first_name=>'Carl', :sim_id => '500')
blackburn = Factory.create(:family, :last_name=>'Blackburn', :first_name=>'Greg', :sim_id => '501')
end
After you can run this task rake delete_all