MZON
MZON

Reputation: 305

Get an argument error in ruby blocks

module Framework
 class CreateTableDefinition 
   attr_accessor :host, :username, :password
 end 
end

def create_table(table_name)
  obj = Framework::CreateTableDefinition.new
  yield(obj) if block_given?
end

create_table :users do |config|
  config.host :localhost
end

And here is the error I get

-:13:in `block in <main>': wrong number of arguments (1 for 0) (ArgumentError)
    from -:9:in `create_table'
    from -:12:in `<main>'

If I change the code to

config.host = :localhost

it works fine. But what I want is to work as described above config.host :localhost

Upvotes: 0

Views: 175

Answers (2)

BroiSatse
BroiSatse

Reputation: 44675

You missed assignment:

config.host = :localhost

Edit

If you want to get rid of assignments, you need to define setter methods without = at the end. This might generate quote a lot of code, so I would rather go with some meta-programming (because it's fun!)

class MyConfigClass
  def self.attributes(*args)
    args.each do |attr|
      define_method attr do |value|
        @attributes[attr] = value
      end
    end
  end

  def initialize
    @attributes = {}
  end

  def get(attr)
     @attributes[attr]
  end 
end

class CreateTableDefinition < MyConfigClass
   attributes :host, :username, :password
end

c = CreateTableDefinition.new
c.host :localhost
c.get(:host)   #=> :localhost 

Upvotes: 2

Andrew
Andrew

Reputation: 1851

Try manually making a method that does what you want instead of using the attr_accessor shortcut.

class CreateTableDefinition 
  attr_accessor :username, :password

  def host(sym)
    @host = sym
  end

  def get_host
    @host
  end
end

If you don't like the idea of writing those methods for every attribute, look into writing your own helper, something like attr_rails_like, and mix it in to the Class object. This article might be helpful.

Upvotes: 0

Related Questions