11

In one of my models I have code like this:

def lendable_category=(i)
  set_category(i)
end

def free_category=(i)
  set_category(i)
end

def skill_category=(i)
  set_category(i)
end

The methods are virtual parameters which I've added so I can save an object using a params hash without coercing the hash in my controller.

It doesn't feel great to say the same thing three times. Is there a better way to create identical methods like this?

2
  • You could pass along an option (that apparently will not be used) do the set_category method, or you could to another method like def opt_category(i,opt) set_category(i) end, can you please explain what do you mean by 'using a params hash without coercing the hash in the controller'? Commented Jan 10, 2013 at 12:35
  • Hi John, the Rails params hash contains something like params[item:[lendable_category:"1",free_category:"",skill_category:""]]. My datamodel on the other hand only contains a category_id field. I don't want to have to parse my params hash in the controller, I'd rather have the Item model handle the different types of category join by itself. The virtual parameters let me do this, but it's not nice having to repeat the same code 3 times. Commented Jan 10, 2013 at 15:42

3 Answers 3

17
%w(lendable free skill).each do |name|
  define_method "#{name}_category" do |i|
    set_category(i)
  end
end
Sign up to request clarification or add additional context in comments.

2 Comments

Brilliant. That is a relief.
I'd also add a comment in the code saying what that is doing, because it isn't obvious, something like # defining lendable_category, free_category and skill_category. Or, use the full method names in the array, not partials. The first time someone goes to search for the method names and can't find them the comment will save the day. Sometimes completely DRYing the code can cause longer term issues by obscuring logic.
16

Alternatively, since your methods aren't doing anything other than calling set_category, you can save a couple of lines by just aliasing the method:

%w(lendable free skill).each do |name|
  alias_method "#{name}_category=", :set_category
end

Comments

4

You can use the alias keyword:

alias lendable_category= set_category 
alias free_category=     set_category 
alias skill_category=    set_category 

1 Comment

I prefer this over dynamically creating method names. If someone ever needed to find those method names, a quick search would locate them.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.