0

I'm new in ruby on rails and have a little confusion on the following code

module Comment
  class CommentScore < ActiveRecord::Base
    self.table_name = 'comment_scores'

    # Associations
    belongs_to :provider_account

    # Scopes
    scope :by_provider_account_id, lambda { |provider_account_id| where(provider_account_id: provider_account_id) }

    # Instance methods
    def set
      return unless self.valid?
      return if unsettable?
      self.positive_count = provider_account.comment.total(:positive)
      self.total          = provider_account.comment.total(:all)
      self.score          = decimal
      self.save!
    end

    def decimal
      positive_count.to_d / total.to_d
    end
  end
end

from my studies, I learned that if the 'self' keyword is used inside a method, it will just actually call a method like in this example, self.positive_count, calls the method 'positive_count' which in rails, means the table column named 'positive_count'.

So I got a bit confused in the 'decimal' method, it just use 'positive_count' without the self? Isn't it a local variable?

3 Answers 3

1

ActiveRecord will define getters and setters for each field in your model, eg. in this case you will get positive_count and positive_count= defined.

You can call the getter easily, like you are doing in your decimal method. However, to call the setter like you are in your set method, you need to use self - otherwise you will simply set a local variable in that method with the value, instead of calling the setter.

Sign up to request clarification or add additional context in comments.

1 Comment

simple and concise. Didn't know activerecord defines getter and setter automatically. When I read that it all just made sense. Thanks.
0

When there is such local variable as positive_count, then the form positive_count without the period and arguments will be interpreted as a local variable. If not, then it will be interpreted as a method. However, methods of the form foo= are obligatorily private.

Comments

0

Based on context and what methods have been defined, Ruby will try and determine if you're making a method call or reading from or assigning to a variable. Unlike other languages where local variables must be defined in advance (int total), or where variables are specified with a different syntax ($int), Ruby has a syntax that's a lot more stripped down. This can lead to some ambiguity.

If there's a method defined with a particular name, like decimal or there's a method that accepts values, such as total=, then a method call will be made when these are referenced. Otherwise it's presumed they're variables.

Use of self avoids ambiguity and forces a method call. It's often used to be sure there's no risk of creating a variable by accident.

Consider the following:

def example
  total = 50
end

Is total a variable, or is there a method called total= that can be used instead? It's not clear from this short example. By default Ruby will treat that as a variable.

Now if you have a column in the database called total, this is discovered after the original model code has been loaded. At that time there was no method called total=. This method is created dynamically after the first instance of that model is instantiated. This is where you get the self-dot notation showing up:

def example
  self.total = 50
end

This ensures you're assigning to the attribute and not creating a local variable by mistake.

Comments

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.