I'm trying to use Factory Girl in a rake task like this:
require 'factory_girl'
require File.expand_path("spec/factories.rb")
namespace :users do
desc "Create sample users for use in development"
task :create_sample_users => :environment do
Factory(:user, :email => "pending#acme.com")
Factory(:approved_user, :email => "user#acme.com")
end
end
However when I run rake users:create_sample_users I get the error uninitialized constant Entry (Entry is the name of one of my app's classes).
Can anyone tell me how to get Factory girl to see my classes? It's working fine in my tests, just failing in my rake tasks.
I'm guessing that Rails hasn't loaded your models at the point you are requiring the factories. Try this:
require 'factory_girl'
namespace :users do
desc "Create sample users for use in development"
task :create_sample_users => :environment do
require File.expand_path("spec/factories.rb")
Factory(:user, :email => "pending#acme.com")
Factory(:approved_user, :email => "user#acme.com")
end
end
For factory_bot which has replaced factory_girl use:
require 'factory_bot'
namespace :users do
desc "Create sample users for use in development"
task :create_sample_users => :environment do
include FactoryBot::Syntax::Methods
create(:user, :email => "pending#acme.com")
end
end
#dmcnally's answer didn't work for me, as I was getting odd errors of constants not found. Instead, I resolved it by shelling out to rails runner:
sh "rails runner 'FactoryGirl.create :user'"
Related
I am creating a model whose name is the input argument in a rake task. After the rake task, I wish to use the model to insert data.
So for example, I call my rake task with input Apple and the model Apple is created. Then I wish to do Apple.insert_all([{name: x},{name: y}...]) in another rake task but I get NameError: uninitialized constant Apple
Here's a better picture of the flow of what I'm doing
Rake::Task["create:fruit"].invoke("Apple") # create model here
Rake::Task["create:insert"].invoke("Apple") # insert data here but getting error
This is how I process the input in the second rake task:
task :insert, [:name] do |t, args|
fruit = args.name
fruit.classify.constantize.insert_all(xxx)
end
Any suggestions for how to go about this?
I created a new project and tried your code. I think the problem is in this line
fruit.classify.constantize.insert_all(xxx)
The code bellow works and create new records. I use a simple rake command to run it.
create.rake file
namespace :create do
desc "TODO"
task :insert, [:name] do |t, args|
klass = Object.const_get(args.name)
klass.create([{name: 'x'},{name: 'y'}])
p klass.count # testing new records have been saved
end
end
Rakefile file
require File.expand_path('../config/application', __FILE__)
Rails.application.load_tasks
task :default do
Rake::Task["create:insert"].invoke("Apple")
end
The rake task itself:
desc "This task creates a new user"
task :create_user, [:email, :password] => :environment do |t, args|
trole = Role.find_by_name('translator')
User.create(
:email => args.email,
:password => args.password,
:password_confirmation => args.password,
:role_id => trole.id)
end
The call:
rake create_user[user#host.com,password]
The output:
rake aborted!
Don't know how to build task 'create_user'
I really got stuck. All the advices I've found, even here, on StackOverflow, either don't cover the situation with two parameters, or are outdated/not working. Please help!
The syntax you've written should work fine in bash, so I'm guessing you're using zsh?
If so, it can't parse the [] correctly and these need to be escaped.
Try using:
rake create_user\[user#host.com,password\]
instead.
I tried putting my script in a class that inherited from my model, like so:
class ScriptName < MyModel
But when I ran rake my_script at the command-line, I got this error:
rake aborted!
uninitialized constant MyModel
What am I doing wrong?
Also, should I name my file my_script.rb or my_script.rake?
Just require the file. I do this in one of my rake tasks (which I name my_script.rake)
require "#{Rails.root.to_s}/app/models/my_model.rb"
Here's a full example
# lib/tasks/my_script.rake
require "#{Rails.root.to_s}/app/models/video.rb"
class Vid2 < Video
def self.say_hello
"Hello I am vid2"
end
end
namespace :stuff do
desc "hello"
task :hello => :environment do
puts "saying hello..."
puts Vid2.say_hello
puts "Finished!"
end
end
But a better design is to have the rake task simply call a helper method. The benefits are that it's easier to scan the available rake tasks, easier to debug, and the code the rake task runs becomes very testable. You could add a rake_helper_spec.rb file for example.
# /lib/rake_helper.rb
class Vid2 < Video
def self.say_hello
"Hello I am vid2"
end
end
# lib/tasks/myscript.rake
namespace :stuff do
desc "hello"
task :hello => :environment do
Vid2.say_hello
end
end
All I had to do to get this to work was put my requires above the task specification, and then just declare the :environment flag like so:
task :my_script => :environment do
#some code here
end
Just by doing that, gave me access to all my models. I didn't need to require 'active_record' or even require my model.
Just specified environment and all my models were accessible.
I was also having a problem with Nokogiri, all I did was removed it from the top of my file as a require and added it to my Gemfile.
I'm creating a new Rails 3.1 application using Cucumber, Devise, and Factory_Girl. I installed successfully Devise and Cucumber. I then created the spec/factories.rb file that contains the following:
require 'factory_girl'
Factory.define :user do |user|
user.name 'Test User'
user.email 'test#email.com'
user.password' testpass'
end
I also added spec/support/devise.rb to add in the test hooks for Devise:
RSpec.configure do |config|
config.include Devise::TestHelpers, :type => :controller
end
In regards to testing, I have not touched anything else and now everytime I run any rake command I get the following (I ran rake spec in this case, just to make sure everything is ready for tests):
rake aborted!
Factory already registered: user
Tasks: TOP => spec => db:test:prepare => db:abort_if_pending_migrations => environment
(See full trace by running task with --trace)
Now if I remove the Factory.define block from the factories file, it runs fine. I've done some Google searching and have come up with absolutely nothing. Since it's saying the Factory is already registered, is Devise for whatever reason, creating a factory already?
When building the following factory:
Factory.define :user do |f|
f.sequence(:name) { |n| "foo#{n}" }
f.resume_type_id { ResumeType.first.id }
end
ResumeType.first returns nil and I get an error.
ResumeType records are loaded via fixtures. I checked using the console and the entries are there, the table is not empty.
I've found a similar example in the factory_girl mailing list, and it's supposed to work.
What am I missing? Do I have to somehow tell factory_girl to set up the fixtures before running the tests?
This is what my test_helper looks like:
ENV["RAILS_ENV"] = "test"
require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
require 'test_help'
class ActiveSupport::TestCase
self.use_transactional_fixtures = true
self.use_instantiated_fixtures = false
fixtures :all
end
My solution to this was to create a db/seeds.rb file which contained model code to generate my seed data:
# Create the user roles
Role.create(:name => "Master", :level => 99)
Role.create(:name => "Admin", :level => 80)
Role.create(:name => "Editor", :level => 40)
Role.create(:name => "Blogger", :level => 30)
Role.create(:name => "User", :level => 0)
And then include it in my spec_helper.rb:
ENV["RAILS_ENV"] = 'test'
require File.expand_path(File.join(File.dirname(__FILE__),'..','config','environment'))
require 'spec/autorun'
require 'spec/rails'
require "#{Rails.root}/db/seeds.rb"
(To be fair, I haven't managed to get autospec to play nice with this yet as it keeps duplicating my seed data, but I haven't tried all that hard either.)
This also has the benefit of being Rails 3 ready and working with the rake db:seed task.
Another option is to add seed.rb in your test or spec directory and require it in your helper file before your factories:
require File.expand_path(File.dirname(__FILE__) + "/seed")
require File.expand_path(File.dirname(__FILE__) + "/factories")
Rails 2.3