rake task variable

13,242

Solution 1

Try this:

namespace :db do
  server_name='myserver'
  task :first_task => :environment do
    connect_to(server_name)
  end

  task :second_task => :environment do
    do_something_with(server_name)
  end
end

Namespaces have access to variables declared before their scope.

Solution 2

I'd like to build on David Sulc's answer, but I recommend using an instance variable instead:

namespace :db do
  @server_name = 'myserver'

  task first_task: :environment do
    connect_to @server_name
  end

  task second_task: :environment do
    do_something_with @server_name
  end
end

The advantage here is that later code can modify @server_name -- something you can't do with a local variable:

namespace :db do
  @server_name = 'server_2'
end
Share:
13,242
Mellon
Author by

Mellon

Software Engineer

Updated on June 06, 2022

Comments

  • Mellon
    Mellon almost 2 years

    I have two Rake tasks under the same namespace like following:

    namespace :db do
      task :first_task => :environment do
             server_name='myserver'
             connect_to(server_name)
      end
    
      task :second_task => :environment do
              server_name='myserver'
              do_something_with(server_name)
      end
    end
    

    As you see, both tasks are under the same namespace and both tasks use server_name='myserver' constant variable.

    It really looks ugly to define the server_name variable twice under the same namespace, how can I have one place defining this variable so both tasks can use it?

  • meandre
    meandre over 9 years
    No, you shouldn't do that. The reason is that you don't know, where that ivar goes to. Neither do I. A rake task is declared using a block, not a class, and therefore the context of the ivar is unclear.
  • David J.
    David J. over 9 years
    @meandre What is the problem with using an instance variable in this way? Can you demonstrate where it could go wrong? Do you have a better suggestion? See the section "Instance Variables in Tasks" in daneharrigan.com/2010/06/rake-tasks-102 for more detailed discussion.
  • David J.
    David J. over 9 years
    @meandre Actually, instance variables defined in the way I show get evaluated in the context of Rake.application.in_namespace(name, &block) (see github.com/jimweirich/rake/blob/v10.3.2/lib/rake/…). I'm not sure what your concern is.
  • meandre
    meandre over 9 years
    Instance variables are evaluated in some object's context (not in a context of a method like in_namespace(). A block/Proc in Ruby gets bound to an object at the moment the block is declared (not when called/yielded - except for instance_eval and some UnboundMethod#bind magic you don't want to know about). As I see, TaskManager#in_namespace makes no use of instance_eval thus leading to sharing all instance variables among all rake tasks. If that mess works for you, it's ok for you, but that's definitely not a better way.
  • David J.
    David J. over 9 years
    @meandre Thanks for digging in and explaining. Having an instance variable shared across all rake tasks is indeed global state at its 'finest'. Would you suggest an alternative way of parameterizing the rake tasks such as server_name as my example showed? (That example is one reason why I suggested this approach, but I'm certainly open to better ways.)
  • knut
    knut almost 3 years
    But get attention, if you define server_name before you define the namespace. Then the variable can be modified outside the namespace definition. See also stackoverflow.com/questions/30328197