Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

defining a task named `load' would shadow an existing method with that name (ArgumentError) #7

Open
singpolyma opened this Issue · 15 comments

5 participants

@singpolyma

I'm using Capistrano and Rake with Rails3 and rake-rails. I've narrowed the error down to happening when it gets to defining the cap task for Rake's db:fixtures:load

/mnt/cache/var/lib/gems/1.9.1/gems/capistrano-2.12.0/lib/capistrano/configuration/namespaces.rb:97:in `task': defining a task named `load' would shadow an existing method with that name (ArgumentError)
        from /mnt/cache/var/lib/gems/1.9.1/gems/cape-1.4.0/lib/cape/capistrano.rb:103:in `block in implement'

The relevant Cap code is:

namespace :rakesnake do
  Cape do
    mirror_rake_tasks do |env|
      env['RAILS_ENV'] = rails_env
    end
  end
end
@njonsson
Owner

Do you get the same exception if you try to mirror just that one task? For example:

namespace :rakesnake do
  Cape do
    mirror_rake_tasks 'db:fixtures:load' do |env|
      env['RAILS_ENV'] = rails_env
    end
  end
end
@njonsson
Owner

Yes, I reproduced this, both ways.

@njonsson
Owner

Unfortunately, this is going to require a workaround for now. Solving the problem will have implications for the Cape DSL.

Capistrano is complaining that we’re creating a recipe that shares the name of a Ruby method. Rake tasks db:fixtures:load and db:schema:load both run afoul of this Capistrano guard because of the existence of Kernel::load in the same scope. I just verified that a Rake task named require would not be able to be mirrored because of the existence of Kernel::require in the same scope.

Here’s the workaround. Use the Cape DSL to ignore tasks and namespaces whose names will collide with existing methods.

# config/deploy.rb
namespace :rake_tasks do
  Cape do
    each_rake_task do |t|
      begin
        mirror_rake_tasks t[:name], :roles => :app do |env|
          env['RAILS_ENV'] = rails_env
        end
      rescue ArgumentError => e
        $stderr.puts "Not mirroring Rake task `#{t[:name]}' because #{e.message}"
      end
    end
  end
end

I’ll probably add a feature to the DSL to allow you to specify a new name for the mirrored task, or possibly a prefix for tasks that collide with existing method names.

@singpolyma

That's not the nicest solution, but it's working for me. Thanks :)

@timuckun

BTW the above solution does not work with capistrano multistage. The rails_env evaluates to :production changing the line to

env['RAILS_ENV'] = rails_env.to_s

solves the issue but of course the core problem is not solved

Not mirroring Rake task db:fixtures:load' because defining a task namedload' would shadow an existing method with that name
Not mirroring Rake task db:schema:load' because defining a task namedload' would shadow an existing method with that name
Not mirroring Rake task test' because defining a namespace namedtest' would shadow an existing method with that name
Not mirroring Rake task test:recent' because defining a namespace namedtest' would shadow an existing method with that name
Not mirroring Rake task test:single' because defining a namespace namedtest' would shadow an existing method with that name
Not mirroring Rake task test:uncommitted' because defining a namespace namedtest' would shadow an existing method with that name

@njonsson
Owner

@timuckun, I regret to say that I have not used the capistrano-ext gem — I have supported multiple stages through manual Capistrano configuration. Please elaborate on what you believe to be the root of the problem. Thanks in advance.

@timuckun

The root of the problem seems to be a naming conflict between capistrano-ext and cape. In my case I chose to only mirror specific tasks but I think in the long run you still need to resolve this issue because capistrano-ext is widely used.

@njonsson
Owner

I agree that Cape needs to provide a way to deal gracefully with recipe name collisions.

Concerning the collision in question, I’ve just confirmed that although the Rake task db:fixtures:load collides with Kernel::load under Capistrano v2.11.2, there is no such problem under Capistrano v2.13.4.

@anujbiyani

Concerning the collision in question, I’ve just confirmed that although the Rake task db:fixtures:load collides with Kernel::load under Capistrano v2.11.2, there is no such problem under Capistrano v2.13.4.

I'm having this problem in Capistrano v2.14.1, so it seems it came back.

@njonsson
Owner

The work on an enhanced DSL is nearing completion. Here’s a preview of how you will be able to resolve this issue using the enhanced DSL.

# config/deploy.rb
namespace :rake_tasks do
  Cape do
    mirror_rake_tasks do |recipes|
      recipes.options[:roles] = :app
      recipes.env['RAILS_ENV'] = lambda { rails_env }

      # The mirrored Capistrano recipe for a Rake task ‘foo’ will be named
      # ‘rake_tasks:foo_task’.
      recipes.rename do |rake_task_name|
        "#{rake_task_name}_task"
      end
    end
  end
end

In the above example, all Rake tasks are mirrored, and their recipe names all get the _task suffix tacked onto them. You could rename only specific tasks by writing multiple mirror_rake_tasks statements that match different sets of Rake tasks.

A cd DSL method that permits running tasks in a directory other than current_path is not demonstrated above.

Feedback on this is welcome.

@timuckun

My solution was to namespace my tasks. I prefixed it with a z: so that it would end up on the bottom of the list when I did a rake -T

Cape do
  each_rake_task do |t|
    #only add the tasks that start with z
    next unless 'z' == t[:name][0, 1]
    begin
      mirror_rake_tasks t[:name], :name => 'tim', :roles => :db do |env|
        env['RAILS_ENV'] = rails_env.to_s
      end
    rescue ArgumentError => e
      $stderr.puts "Not mirroring Rake task `#{t[:name]}' because #{e.message}"
    end
  end
end
@njonsson
Owner

The new DSL is available in bd5a6aa and v1.7.0. It allows you to deal with this issue gracefully, renaming a task that collides with a Ruby method.

@njonsson njonsson closed this
@why-el

Hey @njonsson are you sure this solves the issue? I renamed all tasks but capistrano (version 2.15.5) still errors out and complains I am trying to define tasks in the test namespace.

@njonsson
Owner

@why-el, please paste into this thread the Cape statements you’re using to rename tasks.

@njonsson njonsson reopened this
@why-el

Hey @njonsson sorry I had since reverted to simply defining my tasks manually. What I wrote is exactly what happened but I am actually no longer at the company where this error happened. ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.