0

I want to pass two functions as methods like so:

def add_user_review(user_id, movie_id, set=:training)
  check_set set, @training_data.add_user_review(user_id, movie_id), @test_data.add_user_review(user_id, movie_id)
end

where the check_set method looks like:

# If set is training set, initiate training set function. else, initiate test set function
def check_set(set, training_method, test_method)
  set == :training ? training_method : test_method
end

I have methods that behave one of two ways depending on set (either :training or :test). Both @training_data and @test_data are objects from another class, and training_method will always be called on @training_data, likewise for test_method and @test_data. Each method accepts different parameters (i.e. not all are passing user_id and movie_id).

I need to refactor my code to incorporate a Proc or something. What should I do?

artis3n
  • 810
  • 2
  • 12
  • 23
  • this might help you out http://stackoverflow.com/questions/522720/passing-a-method-as-a-parameter-in-ruby – Joel Feb 06 '15 at 20:26
  • 1
    Speaking of stack overflow, isn't that what results when you invoke `add_user_review`? – Cary Swoveland Feb 06 '15 at 20:27
  • Your `check_set` can be refactored to `def check_set(_, training_method, _); training_method end`. – sawa Feb 06 '15 at 20:54
  • The error that results when I invoke `add_user_review` is undefined method `add_user_review` for nil::NilClass. And this is happening because `@test_data` does not exist. The method is executing both methods before passing the results to `check_set`, when what I want is for `check_set` to decide which method should be called. – artis3n Feb 06 '15 at 20:57
  • Is `check_set` called from other places? – lurker Feb 06 '15 at 20:58
  • @JoelL, I had seen that question earlier, but I'm not sure how it helps me: I don't want to call a block of code, I want to call a method defined in a separate object (`@training_data` refers to an object I defined). – artis3n Feb 06 '15 at 20:58
  • @lurker, yes, `check_set` is called in several methods that all had this same behavior: if set is of a certain type, execute one method, else execute this other method. That's why I'm trying to create this one method that all can refer to. – artis3n Feb 06 '15 at 20:59
  • Here is your answer using `Proc` http://stackoverflow.com/questions/522720/passing-a-method-as-a-parameter-in-ruby – Maged Makled Feb 06 '15 at 21:04
  • @MagedMakled, that post's information is what I was trying to use, but it was not working correctly. See the answer I marked below for an implementation that is working. – artis3n Feb 06 '15 at 21:05
  • @eugene1832, I meant to use a `Proc` in general. did you get it or you still need help? – Maged Makled Feb 06 '15 at 21:28
  • @MagedMakled, ah I see, in that case yes, that is what I went for. I did get it! Thanks to the response below. – artis3n Feb 06 '15 at 22:21

1 Answers1

2

Here is a simple implementation with procs. The proc only gets executed when you do call on it.

 def add_user_review(user_id, movie_id, set=:training)
    check_set set, proc { @training_data.add_user_review(user_id, movie_id) }, proc { @test_data.add_user_review(user_id, movie_id) }
  end

 def check_set(set, training_method, test_method)
   set == :training ? training_method.call() : test_method.call()
 end
Ismael Abreu
  • 16,443
  • 6
  • 61
  • 75
  • Thank you! I was trying to do this by calling `Proc.new( { } ), which was failing. Thank you for showing me the correct syntax. – artis3n Feb 06 '15 at 21:04