In rails 4 app, I am trying to create one rake task. I am trying to include a module feature for it but its not working.
Module file is (/app/models/concerns/user/tags.rb),
module Concerns::User::Tags
extend ActiveSupport::Concern
...
end
Rakefile is (/lib/tasks/keywords.rake),
require "#{Rails.root}/app/models/concerns/user/tags.rb"
include Concerns::User::Tags
namespace :keywords do
desc 'Add data'
task :add => :environment do
puts "Adding"
end
end
When I run this bundle exec rake keywords:add -t getting an error like,
NameError: uninitialized constant Concerns
/vagrant/app/models/concerns/user/tags.rb:1:in `<top (required)>'
/vagrant/lib/tasks/keywords.rake:1:in `<top (required)>'
How can I solve this issue? Please help me.
I think you can try moving the include Concerns::User::Tags inside the task block. If you need the module functionality in several tasks then yes include it in every task. You problem is essentially discussed here Is it possible to include modules in rake task and make its methods available for the task in rails app?
Related
I am trying to upgrade a Rails 6.1.3.1 application from Ruby 2.6.6 to 3.0.0
All the rspec tests run fine and the in development everything seems to work just fine except one thing:
Even the simplest of tasks fails with this error:
"class variable ##debug_missing_translation of ActionView::Base is overtaken by Object"
For example, this simpletask.rake file
task simpletask: :environment do
puts 'Hello'
end
is not able to run as I get the following error:
lxxx#xxx:~/Workspace/edumino$ rails simpletask
rails aborted!
class variable ##debug_missing_translation of ActionView::Base is overtaken by Object
/home/xxx/railsapp/config/environment.rb:5:in `<top (required)>'
/home/xxx/railsapp/bin/rails:5:in `require'
/home/xxx/railsapp/bin/rails:5:in `<top (required)>'
/home/xxx/railsapp/bin/spring:10:in `require'
/home/xxx/railsapp/bin/spring:10:in `block in <top (required)>'
/home/xxx/railsapp/bin/spring:7:in `<top (required)>'
Tasks: TOP => simpletask => environment
(See full trace by running task with --trace)
...so, it turns out the problem was an already existing task. I don't remember exactly why this was necessary but the task had this:
# frozen_string_literal: true
require "#{Rails.root}/app/helpers/cron_helper"
require "#{Rails.root}/app/helpers/notifier_helper"
require "#{Rails.root}/app/helpers/application_helper"
include ApplicationHelper
include ActionView::Helpers::TranslationHelper
include CronHelper
namespace :cron do
task sms: :environment do |_t, _args|
...
end
end
I assume that the guilty code was including the ActionView::Helpers::TranslationHelper
Again, I can't remember why I had to do that at that time. But if you bump into this kind of 'overtaken by' error when upgrading to Ruby 3.0, check your other tasks and see what kinda weird includes you might have had. In my case, since I didn't need the old task, I just removed it.
I'm starting with RoR, so I have a question about the implementation of rake tasks.
I have a rake file with a few lines that made some scheduled tasks with Twitter Gem Api.
Run the rake works properly, but I want to order my code.
Now the rake looks like this:
desc "This task is called by the scheduler"
task :update_feed => :environment do
require 'twitter'
client = Twitter::REST::Client.new do |config|
#Client configs
end
here.i.do.some.stuff
end
I'm pretty sure that have the client configs right there isn't a good idea.
On the other hand, I want to be able to save the methods within the model so I can use them elsewhere.
So, I'm trying to do this unsuccessfully:
#On tweet.rb model file:
class Tweet < ApplicationRecord
validates :tweet_id, uniqueness: true
def here_i_do_some_stuff
#do some stuff
#Plus config the client
end
end
#And the rake file
task :update_feed => :environment do
Tweet.here_i_do_some_stuff
end
And that's not working for
rake aborted!
NoMethodError: undefined method `here_i_do_some_stuff' for Tweet (call 'Tweet.connection' to establish a connection):Class
I don't really know how to do this, I tried other ways like write on other files and require them, but I think this is the correct way, but I don't know how to make it run properly.
Thanks, JR.
I have a task that want to run after I run rails tmp:clear
namespace :myapp do
task :clear do
# do some stuff
end
end
I've learned that I can do it by enhancing that task:
Rake::Task['tmp:clear'].enhance(['myapp:clear'])
The problem is that when my code is loaded, tmp:clear is undefined, so it fails:
$ rails tmp:clear
rails aborted!
Don't know how to build task 'tmp:clear' (See the list of available tasks with `rails --tasks`)
myapp/lib/tasks/clear.rake:7:in `<top (required)>'
Rails tasks are loaded after local tasks. You need to require 'rails/tasks' before to circumvent that.
Complete solution:
require 'rails/tasks'
namespace :myapp do
task :clear do
puts "do some stuff"
end
end
Rake::Task['tmp:clear'].enhance(['myapp:clear'])
I got a rake task which invokes other rake tasks, so my development data can be easily reset.
the first rake task (lib/tasks/populate.rake)
# Rake task to populate development database with test data
# Run it with "rake db:populate"
namespace :db do
desc 'Erase and fill database'
task populate: :environment do
...
Rake::Task['test_data:create_company_plans'].invoke
Rake::Task['test_data:create_companies'].invoke
Rake::Task['test_data:create_users'].invoke
...
end
end
the second rake task (lib/tasks/populate_sub_scripts/create_company_plans.rake)
namespace :test_data do
desc 'Create Company Plans'
task create_company_plans: :environment do
Company::ProfilePlan.create!(name: 'Basic', trial_period_days: 30, price_monthly_cents: 4000)
Company::ProfilePlan.create!(name: 'Professional', trial_period_days: 30, price_monthly_cents: 27_500)
Company::ProfilePlan.create!(name: 'Enterprise', trial_period_days: 30, price_monthly_cents: 78_500)
end
end
when I run bin/rake db:populate then i get this error
rake aborted! LoadError: Unable to autoload constant
Company::ProfilePlan, expected
/home/.../app/models/company/profile_plan.rb to define it
but when I run the second rake task independently it works well.
The model (path: /home/.../app/models/company/profile_plan.rb)
class Company::ProfilePlan < ActiveRecord::Base
# == Constants ============================================================
# == Attributes ===========================================================
# == Extensions ===========================================================
monetize :price_monthly_cents
# == Relationships ========================================================
has_many :profile_subscriptions
# == Validations ==========================================================
# == Scopes ===============================================================
# == Callbacks ============================================================
# == Class Methods ========================================================
# == Instance Methods =====================================================
end
Rails 5.0.1
Ruby 2.4.0
The App was just upgraded from 4.2 to 5
It works when I require the whole path:
require "#{Rails.root}/app/models/company/profile_plan.rb"
But this seems strange to me, because in the error message rails has the correct path to the Model. Does someone know why I have to require the file when invoked from another rake task?
Thank you very much
Well, it seems that rake doesn't eager load, so when you call the create_company_plans.rake alone it loads the referred objects, however when you invoke it from another rake, it doesn't know you will need them and so they are not loaded.
You can take a look at this other QA which was similar to yours.
I think maybe you don't need to require the whole path, just:
require 'models/company/profile_plan'
From what I understand, you can probably overcome the problem by reenable ing and then revoke ing the task as given below. Pardon me if this doesn't work.
['test_data:create_company_plans', 'test_data:create_companies'].each do |task|
Rake::Task[task].reenable
Rake::Task[task].invoke
end
There is more info on this stackoverflow question how-to-run-rake-tasks-from-within-rake-tasks .
I have a problem creating a Rails plugin, lets call it Mplug. The plugin is pretty much only a rake task, but with a library that the rake task uses.
The problem is to require files. Lets say that this is the rake task:
namespace :mplug do
task :create do
Mplug::Indexer.new
end
end
This will not recognize the constant Mplug. So I thought I needed to require it.
require 'mplug'
namespace :mplug do
task :create do
Mplug::Indexer.new
end
end
But then I get this message.
no such file to load -- mplug
So, ok. Lets try to give the path to the plugin then.
require 'vendor/plugins/mplug/lib/mplug'
namespace :mplug do
task :create do
Mplug::Indexer.new
end
end
This actually works. However, except that I guess that this is a bad way to do it, I now have to require the files in my plugin as if I was in the rails root. For example:
module Mplug
end
require 'mplug/indexer'
Now has to be:
module Mplug
end
require 'vendor/plugins/mplug/lib/mplug/indexer'
Which I do not want to do of course.
Is there any neat way to solve this?
Thanks!
The easiest solution to this problem would be to register the rake task using the Rails::Railtie API. In lib/mplug.rb, define your Railtie:
module Mplug
class Railtie < ::Rails::Railtie
rake_tasks do
load "mplug/rails.rake"
end
end
end
Then, in lib/mplug/rails.rake:
namespace :mplug do
task :create do
Mplug::Indexer.new
end
end
Then, make sure your plugin is defined in your Gemfile. If your plugin is in vendor/plugins, add this line to your Gemfile:
gem "mplug", :path => "vendor/plugins/mplug"
If you push the plugin to a git repo, use :git.
Now, rake mplug:create will be available! If you want it to show up in rake -T, make sure you add a description:
namespace :mplug do
desc "creating an mplug"
task :create do
Mplug::Indexer.new
end
end
One option is to use the FILE constant, and then provide the rest of the path relative to the current file:
require File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib', 'mplug')
(if your rake task file is in your plugin_root/tasks...)