How to import Model into a custom rake task? - ruby-on-rails

In my lib/tasks folder I added a new .rake file.
In the rake task, I am doing this:
p = Post.new( ....)
p.save!
When I run my task, I get the error:
rake aborted!
uninitialized constant Post
What do I have to do to import my Post model?

I'm thinking you're probably missing the environment declaration. This is necessary in order for Rake to know about your Rails environment. Your rake task call should look something like this:
task :my_rake_task => [:environment] do
# Your code here
end
Let me know if that solves the problem!

You want to make the task dependent on the rails environment. You can do so by specifying the => :environment after the task declaration as such:
namespace :my_task do
desc "an example task"
task :create_post => :environment do
Post.new .... # the rest of the implementation
end
end

Related

Rails dynamically create model and use it

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

Prepend to existing rake task

Defining an existing rake task again appends to the original, but I'd like to prepend to the db:migrate task. I want to raise an error beforehand in some cases. Is there a good way to prepend to an existing rake task?
Try adding a db:custom task on 'db' namespace and invoke db:migrate with enhance method
# add your custom code on db:custom
namespace 'db' do
task 'custom' do
puts "do custom db stuff"
end
end
# invoke db:migrate
Rake::Task['db:migrate'].enhance [:custom]
Might be better to define your own task and call db:migrate inside.
namespace :custom_db do
desc 'migrate db if condition true'
task :migrate do
if true #your condition
Rake::Task['db:migrate'].invoke
else
#process errors
end
end
end

Using Rake with Rufus

I'm trying to user rake and rufus, both of which I am new to. I want to have Rufus call my rake task but I am getting the following error. Don't know how to build task 'inbox:process_inbox'
lib/tasks/inbox_tasks.rb
namespace :inbox do
task :process_inbox do
logger = Logger.new(Rails.root.to_s + "/log/scheduler.log")
logger.info "Rufus Here!"
end
end
rufus_scheduler.rb
require 'rufus-scheduler'
require 'rake'
scheduler = Rufus::Scheduler.new
scheduler.every '10s', :first_at => Time.now + 3 do
Rake::Task["inbox:process_inbox"]
end
As #jmettraux (the creator of rufus-scheduler!) has already answered, the problem is that the rake task is defined in a .rb file instead of .rake file.
Adding some more details to help in the future.
While creating a new rake task, you could get the rails generator to automatically create the file with appropriate structure.
Example: Running
> rails g task inbox process_inbox
create lib/tasks/inbox.rake
will create a file named lib/tasks/inbox.rake with content:
namespace :inbox do
desc "TODO"
task process_inbox: :environment do
end
end
Having a DESC in the task definition is important; that allows for verifying that the rake task is defined and available, by running either rake -T inbox or rake -T | grep inbox
> rake -T inbox
rake inbox:process_inbox # TODO
Could this one help?
How to build task 'db:populate' (renaming inbox_tasks.rb to inbox_tasks.rake)
(did a simple https://www.google.com/?#q=rails+don%27t+know+how+to+build+task ...)

Overriding rails' default rake tasks

I have a Rails 2.2 project in which I want to override the functionality of the rake db:test:prepare task. I thought this would work, but it doesn't:
#lib/tasks/db.rake
namespace :db do
namespace :test do
desc "Overridden version of rails' standard db:test:prepare task since the schema dump used in that can't handle DB enums"
task :prepare => [:environment] do
puts "doing db:structure:dump"
Rake::Task['db:structure:dump'].invoke
puts "doing db:test:clone_structure"
Rake::Task['db:test:clone_structure'].invoke
end
end
end
I get the standard task's behaviour. If I change the name of the task to :prepare2 and then do rake db:test:prepare2, then it works fine. The natural conclusion I draw from this is that my rake tasks are being defined before the built-in Rails ones, so mine is overridden by the standard :prepare task.
Can anyone see how I can fix this? I'd rather override it than have to use a new task. Thanks, max
If you define a rake task that already exists, its execution gets appended to the original task's execution; both tasks will be executed.
If you want to redefine a task you need to clear the original task first:
Rake::Task["db:test:prepare"].clear
It's also useful to note that once a task has been executed in rake, it won't execute again even if you call it again. This is by design but you can call .reset on a task to allow it to be run again.
You have to remove the default task before adding your own:
Rake.application.instance_variable_get('#tasks').delete('db:test:prepare')
namespace 'db' do
namespace 'test' do
task 'prepare' do
# ...
end
end
end
A fairly popular idiom is to create a convenience method called remove_task like so:
Rake::TaskManager.class_eval do
def remove_task(task_name)
#tasks.delete(task_name.to_s)
end
end
def remove_task(task_name)
Rake.application.remove_task(task_name)
end
(Source: drnic/newgem)
Create a new project.rake file at lib/tasks/, and paster below code into it.
namespace :mv do
desc "Display hint and info for your rails 4 project"
task info: :environment do
puts 'Run rake test to test'
end
end
task(:default).clear.enhance ['mv:info']
inspired by Krasimir Angelov's blog

Newbie, about Rake task syntax

In Rake task definition, like following:
desc 'SOME description'
task :some_task => :environment do
# DO SOMETHING
end
What does the :some_task in task :some_task => :environment means?
Is it the method name which will be invoked in the DO SOMETHING part?
Can :some_task be any arbitrary string which describe the task?
In fact, when you're creating a rake task, :some_task is the name of the task you are calling.
For instance, in this case, you will call rake some_task
You also could define namespaces for your tasks :
namespace :my_tasks do
desc "My first task"
task :first_task => :environment do
# DO SOMETHING
end
end
And then you will call rake my_tasks:first_task in your console.
Hope it will help you,
Edit:
As explained by Holger Just, the :environment executes the "environment" task and if you are on rails, loads the environment. This could take a long time but il also helps you if your tasks works with the database.
With your example, you define a task called some_task which can be invoked by calling rake some_task on the command line.
It will depend on the environment task which will be rune before your new some_task. In rails, the environment task sets up the rails environment (loading libraries, preparing database connection, ...) which is quite expensive and thus optional.

Resources