ZK Zhao
ZK Zhao

Reputation: 21513

Ruby: How to use hash as argument of a method

I want to define a helper in Rails:

# Usage:
# selector_link('This is New', tab: 'new')
# selector_link('This is like sorter', sort: 'like_count')
# selector_link('This is number 7', number: 7)
def selector_link2(link_text, param_name: param_content)
  link_to link_text, url_for(param_name: param_content), class: ('active'if params[:param_name] == param_content)
  # Should Generate:
  # link_to link_text, url_for(tab: 'new'), class: ('active'if params[:tab] == 'new')
  # link_to link_text, url_for(sort: 'like_count'), class: ('active'if params[:sort] == 'like_count')
  # link_to link_text, url_for(number: 7), class: ('active'if params[:number] == 7)
end

The problem is that, I don't know how to make the key in url_for(key: path) to accept the input hash's key, and params[:key] also seems a invalid syntax.

What is the correct way of wrting this method?

UPDATE: This is what I end up with

def selector_link2(link_text, link = {})
  key = link.first[0]
  value = link.first[1]
  link_to link_text, url_for(link), class: ('active'if params[link[key].to_s] == link[value])
end

Upvotes: 0

Views: 80

Answers (1)

Kokizzu
Kokizzu

Reputation: 26818

It's called named parameter or keyword argument, so that

def x(a, b: 'test')
  puts "a = #{a}"
  puts "b = #{b}"
end

could be called as:

x 123, b: 'yay'
# a = 123
# b = yay

You could also type it like this:

def x(a, b: nil) 
  b ||= anything      
end

EDIT 1: So in your case (if I'm not misunderstood), it should be something like this:

def selector_link(link_text, tab: path)
  link_to link_text, url_for(key: tab), class: ('active' if tab == 'new')
end

EDIT 2: Or something like this:

def selector_link(link_text, opt={})
  link_to link_text, url_for(opt), class: ('active' if opt[:tab] == 'new')
end

Both function can be called as selector_link('a',tab:'new')

EDIT 3 for your last question edit, it should be something like this:

def selector_link(link_text, opt={})
  active = nil
  active = 'active' if !opt[:tab].nil? and opt[:tab] == 'new'
  active = 'active' if !opt[:sort].nil? and opt[:sort] == 'like_count' 
  link_to link_text, url_for(opt), class: active
end 

EDIT 4 If Rail's helper can access params, you could type it like this:

def selector_link(link_text, opt={})
  key = opt.first[0] # get the first :key or :param_name
  link_to link_text, url_for(opt), class: ('active' if opt[key].to_s == params[key].to_s)
end 

# call it using:
selector_link('This is New', tab: 'new')
selector_link('This is like sorter', sort: 'like_count')
selector_link('This is number 7', number: 7)

If params not accessible from helper, you must pass it manually:

def selector_link(link_text, params, opt={})
  key = opt.first[0]
  link_to link_text, url_for(opt), class: ('active' if opt[key].to_s == params[key].to_s)
end 

# call it using:
selector_link('This is New', params, tab: 'new')
selector_link('This is like sorter', params, sort: 'like_count')
selector_link('This is number 7', params, number: 7)

EDIT 5 last update, for the repetitive part

def selector_link2(link_text, link = {})
  key, value = link.first
  link_to link_text, url_for(link), class: ('active' if params[key].to_s == value.to_s)
end

Upvotes: 2

Related Questions