简体   繁体   中英

Rails helper methods: @ vs normal variable

In Michael Hartl's rails tutorial we have a current_user method defined as such:

  # Returns the user corresponding to the remember token cookie.
  def current_user
    if (user_id = session[:user_id])
      @current_user ||= User.find_by(id: user_id)
    elsif (user_id = cookies.signed[:user_id])
      user = User.find_by(id: user_id)
      if user && user.authenticated?(:remember, cookies[:remember_token])
        log_in user
        @current_user = user
      end
    end
  end

At first I assumed @current_user was needed as opposed to some other local variable like the_current_user (assuming you can't use current_user since that's the name of the method.

When using helper methods that return something, do we need an @ variable or can we just use any variable type? (I saw other helper_methods use normal variable_names ). (Im assuming @current_user was just convenient)

@ makes variables available throughout the class.

If was just current_user instead of @current_user it would only be accessible inside of that specific method.

You can use current_user as a variable name inside of a method named current_user


you don't need to use @ before an instance variable to return a value.

def some_method
  user = "Jimmy"
  user
end

> puts some_method
"Jimmy"

Here's a common Ruby idiom, up close:

def current_user
  @current_user ||= User.find_by(id: something)
end

You can call current_user as often as you like, now, because it will only spend time hitting the database the first time you call it. On subsequent calls, @current_user has a value, so the ||= evaluates trivially as @current_user = @current_user .

The effect lasts as long as the @ instance exists. If it's a controller, it will last for the current action, and then disappear. This means a new action with a different user will not trip over the previous value of @current_user .

Because def current_user occupies a namespace different from @current_user , the Ruby idiom is to name the "memento pattern" variable the same as the method it optimizes.

Your example makes the memento pattern a little confusing, because there are two ways to generate a current user.

You can return normal variable in helper methods.

@ is just a syntax used to define an instance variable.

@current_user is just a convention, you can use any name like @whatever_user

For example, if we are using current_user instead of @current_user then you will not be able to access current_user from any of your views.

For example, if you want to show the name of the user if the user is signed in:

<%= @current_user.name if @current_user %>

It is possible only because we have used the instance variable.

Following will help you in knowing more about instance variable:

https://ruby-doc.org/docs/ruby-doc-bundle/UsersGuide/rg/instancevars.html http://ruby-for-beginners.rubymonstas.org/writing_classes/instance_variables.html

To know about all the types of variables available in Ruby: https://www.studytonight.com/ruby/types-of-variables-in-ruby

Side Note

@current_user ||= User.find_by(id: user_id)

This pattern is called memoization. It is a very common pattern in Ruby/Rails. You can read more about it here:

https://www.justinweiss.com/articles/4-simple-memoization-patterns-in-ruby-and-one-gem/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM