Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the cleanest way to define a constant string that involves a variable in Ruby?

Tags:

ruby

calabash

For some context, a lot of my code has the same lines of text throughout it (we are using Calabash to do iOS automation, if that gives you an idea).

For example: "all label marked:'#{name}'" is used 8 times in a particular class.

I would prefer to be able to have a constant that uses that text, but if I throw it at the top of the class, of course the variable "name" has not been set yet. Without defining a method that takes a parameter and returns a string, is there a way to do something essentially like this that can exist at the top of the class, but not be evaluated until it's used?:

class ClassName
  extend Calabash::Cucumber::Operations

  @NAME_CONSTANT = "all label marked:'#{name}'"

  def self.method_name(name)
    query("#{@NAME_CONSTANT} sibling label marked:'anotherLabel' isHidden:0")
  end
end

If you use the syntax I mentioned, you get this error: undefined local variable or method `name' for ClassName

like image 310
Teresa Peters Avatar asked Nov 04 '13 18:11

Teresa Peters


People also ask

How do you define a constant variable in Ruby?

A constant doesn't require any special symbol or syntax to declare. You just need to make the first letter an uppercase letter.

How do you define a constant string?

A string constant is an arbitrary sequence of characters that are enclosed in single quotation marks (' ').

How do you assign a string variable in Ruby?

Creating Strings: To create the string, just put the sequence of characters either in double quotes or single quotes. Also, the user can store the string into some variable. In Ruby, there is no need to specify the data type of the variable.

How do you write a string constant?

A string constant is enclosed in double quotation marks ("). Any ASCII character is a valid character in a constant string.


2 Answers

You could use String#% to insert the string later.

class ClassName
    @NAME_CONSTANT = "all label marked:'%{name}'"

    def self.method_name(insert_name)
        query("#{@NAME_CONSTANT} sibling label marked:'anotherLabel' isHidden:0" % {name: insert_name})
    end

    def self.query(string)
        puts string
    end 
end 

ClassName.method_name('test')
#=> "all label marked:'test' sibling label marked:'anotherLabel' isHidden:0"
like image 103
Justin Ko Avatar answered Dec 05 '22 04:12

Justin Ko


I agree with @Sergio. Don't define a constant string that includes a variable. Just use a method. Including a variable in a constant seems like a bad idea. Constants shouldn't be dynamic, by definition.

If you really want to include a variable in a constant string, you can assign a lambda to a contstant, like so:

class ClassName
  extend Calabash::Cucumber::Operations

  NAME_CONSTANT = ->(name) { "all label marked:'#{name}'" }

  def self.method_name(name)
    query("#{NAME_CONSTANT.call(name)} sibling label marked:'anotherLabel' isHidden:0")
  end
end

I removed the @ before the constant, since including it creates a class-level instance variable, not a constant.

I really wouldn't use the code sample I posted, though. Just use a method. Avdi Grimm has a good post called "Do we need constants?" where he describes some of the benefits of using methods instead of constants.

like image 20
Michael Stalker Avatar answered Dec 05 '22 06:12

Michael Stalker