Ahmed Fathy
Ahmed Fathy

Reputation: 529

What is the correct way to define functions to use in a rails model?

If one of my model functions does something complex or its logic has some part that can be reused in another model function, is it correct to define a third function inside the model so that it becomes an instance method or define it as a class method?

My first solution was to do something like this in my model file(say user.rb):

#Some Function
def magic_function
  return true
end

class User < ActiveRecord::Base
  def first_function
    return magic_function
  end

  def second_function
    return 1 if magic_function
    return 0
  end
end

but I can't stub the magic_function while doing rspec tests and browsing through the internet makes me believe that what I did is not usually done by others... Some seem to use modules but in my case, this function is only needed within this file. I just defined it to DRY my code out or to make it more readable but I don't think it should be an instance method as I don't need to call it from outside this file, neither does it need to be a class method for the same reason. Where is the right place to define a function like this?

Upvotes: 1

Views: 70

Answers (1)

Andrew Marshall
Andrew Marshall

Reputation: 96934

It’s hard to say without knowing what magic_function does, but it seems you want it to be private:

class User < ActiveRecord::Base
  def first_function
    return magic_function
  end

  def second_function
    return 1 if magic_function
    return 0
  end

  private

  def magic_function
    return true
  end
end

This will allow you to call magic_function from other instance methods of User, but it cannot be called from outside it:

user = User.new
user.first_function  # works
user.magic_function  # NoMethodError: private method `magic_function' called

Note, however, that you should still not stub magic_function simply because you should never stub the system under test. It should be tested implicitly through the public methods. If you want to test it separately, you should put it in a new Class or Module and call out to it from User.

Upvotes: 5

Related Questions