uninitialized constant error when run my rake task, why? - ruby-on-rails

I have a class which is NOT an ActiveRecord.
the class is located under lib/room/
lib/room/car_painter.rb
class ROOM::CarPainter
def paint_car
...
end
end
Then, I have a rake task:
under /lib/tasks/
/lib/tasks/new_car_painting.rake
namespace :new_car do
desc "Paint new cars"
task :paint => :environment do
painter = ROOM::CarPainter.new #ERROR HERE- uninitialized constant
painter.paint_car
end
end
When I run rake new_car:paint, I got the error message "uninitialized constant ROOM::CarPainter", Why??
--EDIT---
I also tried to use class function instead of instance function, like following:
class ROOM::CarPainter
def self.paint_car
...
end
end
and
namespace :new_car do
desc "Paint new cars"
task :paint => :environment do
ROOM::CarPainter.paint_car #ERROR HERE- uninitialized constant
end
end
But I get the same error message...why again

This is rake file.
desc 'This is just a testing rake task'
task :update_ts => :environment do |t,args|
puts 'ashish is great'
include TestLib
print_sm
end
This is lib/test_lib.rb file.
module TestLib
def print_sm
puts "Hello World in Lib Directory"
end
end
You just need to include that module.
Edited:
I guess problem is your lib/* folder loading.
Try with this in your application.rb file:
config.autoload_paths += Dir["#{config.root}/lib/**/"]

In rails you need to require from the root and rails 3 practice is the following
require Rails.root.join('path')

Related

NameError: uninitialized constant AppName::Loader::ModelImport::MyModel

I have a namespace issue. MyModel is just a normal Rails Model. However, my code seems to be namespacing it under the namespace I created, I need a way to reference it directly without the AppName::Loader::ModelImport namespace.
Error:
NameError: uninitialized constant AppName::Loader::ModelImport::MyModel
Rake task:
require 'csv'
require_relative '../appname/loader/model_import'
namespace :app_name do
namespace :loader do
desc "Loads data into Database"
task model_import: :environment do
include AppName::Loader::ModelImport
end
end
end
Service Object
./appname/loader/model_import.rb
module AppName
module Loader
module ModelImport
record_set = []
file_name = File.join(Rails.root, 'lib','appname','loader','data' ,'data.txt')
CSV.open(file_name, "r", { :col_sep => "\t", quote_char: nil, row_sep: "\r\r\n" }).each do |row|
record_set << MyModel.new(
company_name: row[1],
address1: row[2],
address2: row[3],
city: row[4],
state_code: row[5],
zip_code: row[6]
)
end
MyModel.import record_set
end
end
end
I tried:
::MyModel.new()
and also got the >>NameError: uninitialized constant MyModel, so I wonder if rails is not loading properly. However, I thought task model_import: :environment do loads Rails.
My application.rb file has..
config.eager_load_paths << Rails.root.join("lib")
If I use Pry, I can see the 'Rails' constant is loaded. However, I can not access any of my models. For example, User does not load, nor any other.
Solution per comments by Tom Lord:
require needed to be evaluated after the environment has been loaded.
If you write a module the code inside it may automagically get executed just because you required the module. For example:
module AppName
module Loader
module ModelImport
puts 'wtf' # this may get run but you won't see it
end
end
end
However if you have at least method defined it can be called
module AppName
module Loader
module ModelImport
def self.wtf
puts 'wtf'
end
end
end
end
Now if this file is saved in lib/app_name/loder/model_import.rb you can run it like this:
require_or_load 'lib/app_name/loader/model_import'
# and now you can do
AppName::Loader::ModelImport.wtf
=>wtf
So you need to first define a usable module, then you can require it, then you can call methods on it.

can i add rake task to my rails app by making gem?

I want to add original rake task to my rails app by making gem. But, I couldn't.
Please tell me my mistake.
In my gem file
>lib/gem_test.rb
require "gem_test/version"
require 'gem_test/railtie' if defined?(Rails) && Rails.version >= "3"
module GemTest
#this is dummy method for loading check
def self.hogehoge
"hogehoge"
end
end
>lib/gem_test/railtie.rb
module GemTest
class Railtie < Rails::Railtie
rake_tasks do
load "tasks/gem_test.rake"
end
end
end
>lib/tasks/gem_test.rake
namespace :fugafuga do
desc "fugafuga"
task :piyopiyo do
puts "piyopoyo"
end
end
and, Gemfile in my rails app,gem gem_test, git:mygitrepository. But I don't find fugafuga:piyopiyotask in result of rake -T.
If need more infomation, see my repository
I think you must require rake in your rakefile:
namespace :fugafuga do
require 'rake' <----
desc "fugafuga"
task :piyopiyo do
puts "piyopoyo"
end
end

Rails not including modules on Models when run in Rake

In Rails 3.2.16, I have a model:
class Person < ActiveRecord::Base
module Testmodule
def testmethod
puts "It's included"
end
end
include Testmodule
end
when I run bundle exec rails c, I can type Person.new.testmethod and get the expected result
If I create a small rake task:
task :myraketask => :environment do
Person.new.testmethod
end
I receive an error that testmethod isn't defined on Person.
However, if I explicitely set eager loading in the rake task, it will work:
task :myraketask => :environment do
Rails.application.eager_load!
Person.new.testmethod
end
If I create a brand new Rails project, I cannot replicate the error. Can anybody point out to me what may be wrong in my project that is causing the error in the first rake task?

Is it possible to include modules in rake task and make its methods available for the task in rails app?

In our rails 3.2.12 app, there is a rake task created under lib/tasks. The rake task needs to call a method find_config() which resides in another rails module authentify (module is not under /lib/). Can we include Authentify in rake task and make method find_config() available to call in the rake task?
Here is what we would like to do in the rake task:
include Authentify
config = Authentify::find_config()
Thanks for comments.
require 'modules/module_name'
include ModuleName
namespace :rake_name do
desc "description of rake task"
task example_task: :environment do
result = ModuleName::method_name()
end #end task
end
This works for me. Since your Module is not in /lib you might have to edit how it is required. But it should work. Hope it helps.
PLEASE PAY ATTENTION TO THIS AND SAVE SOME RANDOM HEADACHES!! .
Don't include your module before your namespace:
include YourModule
namespace :your_name do
desc 'Foo'
task foo: :environment do
end
end
or inside your namespace:
namespace :your_name do
include YourModule
desc 'Foo'
task foo: :environment do
end
end
as that will include your module for the whole app and it could bring you a lot of troubles (like me adding in the module some :attr_accessors and breaking factory-bot functioning or other things it has happened in the past for this same reason).
The "no issues" way is inside of your task's scope:
namespace :your_name do
desc 'Foo'
task foo: :environment do
include YourModule
end
end
And yes, if you have multiple tasks, you should include in each of them:
namespace :your_name do
desc 'Foo'
task foo: :environment do
include YourModule
end
desc 'Bar'
task bar: :environment do
include YourModule
end
end
or simply call your method directly if you're only calling a method once in the task:
namespace :your_name do
desc 'Foo'
task foo: :environment do
YourModule.your_method
end
desc 'Bar'
task bar: :environment do
YourModule.your_method
end
end
How to require a Rails service/module in a Rake task?
I had the same problem and manage to solve it by requiring the rails files inside the rake task.
I had a rake task named give_something defined in the file lib/tasks/a_task.rake.
Within that task I needed to call the function give_something from the module AService which lives in the file app/services/a_service.rb
The rake task was defined as follows:
namespace :a_namespace do
desc "give something to a list of users"
task give_something: :environment do
AService.give_something(something, users)
end
end
I was getting the error: uninitialized constant AService
To solve it I had to require the module not at the beginning of the file a_task.rake, but inside the rake task:
namespace :a_namespace do
desc "give something to a list of users"
task give_something: :environment do
require 'services/a_service' # <-- HERE!
AService.give_something(something, users)
end
end
In rails 5.x.x we can do as-
Module file exist her app/lib/module/sub_module.rb like-
module Module
module SubModule
def self.method(params1, params2)
// code goes here...
end
end
end
and my rake_task presented here /lib/tasks/my_tasks.rake as-
namespace :my_tasks do
desc "TODO"
task :task_name => :environment do
Module::SubModule.my_method(params1, params2)
end
end
Note:- the above task file presented in outer lib not in app/lib
Now run the task using following command-
rake my_tasks:task_name
from app directory not from rails console
That worked for me !!!

How do I access one of my models from within a ruby script in the /lib/ folder in my Rails 3 app?

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.

Resources