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

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

Related

Rake tasks in separate gems conflicting

I am building two separate gems, using Railties to bring in rake tasks from each gem. The tasks are in different namespaces, and when I bring in each separately in a Gemfile, the task shows up in rake -T, but when both gems are in the same Gemfile, only the second gem's task shows up. It's as if the second gem's task stomps the first, despite namespacing.
class AfsTest::Railtie < Rails::Railtie
railtie_name :afs_test
rake_tasks do
load 'tasks/config.rake'
end
end
namespace :afs do
namespace :test do
desc 'Configure afs_test gems'
task :config do
puts 'placeholder'
end
end
end
and
class AfsDevTest::Railtie < Rails::Railtie
railtie_name :afs_dev_test
rake_tasks do
load 'tasks/config.rake'
end
end
namespace :afs do
namespace :dev_test do
desc 'Configure afs_dev_test gems'
task :config do
Rails::Generators.invoke('rspec:install')
end
end
end
(Yes, I know the gems don't do much - that's not the point here. The point is that one stomps the other.)

Determining whether gem was called as Rake task

I'm writing a gem that includes some rake tasks. I have some code in the before_configuration method that I want to run when my gem is loaded by the app at runtime, but NOT when a task is run with rake. How can I determine that?
lib/mygem/tasks.rake:
namespace :mygem do
task :dosomething do
puts "DONE"
end
end
lib/mygem/railtie.rb:
require "rails"
module Mygem
class Railtie < ::Rails::Railtie
config.before_configuration do
#is_rake_task = ?
if !is_rake_task
# Do something
end
end
end
end
Rake is only defined in rake context.
So, you could simply go something like that :
if defined? Rake
# rake specific stuff
else
# non rake stuff
end
Edit :
While this will work perfectly with rails s, there's a problem with zeus on development environment : zeus will require rake.
If this is a problem, if think you can take advantage of Rake.application, which sets an instance variable when a rake task is executed.
I've tested this in a zeus s context :
> Rake.instance_variable_defined? :#application
false
And in a rake <task> context :
> Rake.instance_variable_defined? :#application
true
So, a complete solution would be :
if defined?( Rake ) and Rake.instance_variable_defined?( :#application )
# rake specific stuff
else
# non rake stuff
end

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.

uninitialized constant error when run my rake task, why?

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')

Rails plugin require issues

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...)

Resources