Search code examples
ruby-on-railsrubysession-cookies

How do I display the value of a session variable in Ruby/Rails?


First I don't know if I'm declaring a session variable correctly. Also, I put it in the application controller, because I know it will run. If there is a better place to put this, then please let me know. The desired outcome is a user selects the team they want all their work to save to during the session. Then when objects are saved they use the session variable :current_team instead of :current_user. By default on creation a team will be created for each new user. That is why I'm querying for the first team for each user. During the session I plan for the user to select the team they are working/contributing for and the selection persist until they change it.

application_controller.rb

class ApplicationController < ActionController::Base
  before_action :authenticate_user!
  before_action :set_current_team

  def set_current_team
    return unless session[:current_team]
    session[:current_team] = Team.first.where(user_id: current_user).id
  end


end

index.html.erb

<p><%= session[:current_team] %></p>

output

Processing by PagesController#index as HTML
  User Load (0.4ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2  [["id", 1], ["LIMIT", 1]]
  ↳ /home/dev/.rbenv/versions/2.5.2/lib/ruby/gems/2.5.0/gems/activerecord-5.2.3/lib/active_record/log_subscriber.rb:98
  Rendering pages/index.html.erb within layouts/application
  Rendered pages/index.html.erb within layouts/application (0.5ms)
  Rendered shared/_navigation.html.erb (2.9ms)
Completed 200 OK in 172ms (Views: 168.3ms | ActiveRecord: 0.4ms)

My models are Team, User, and a join table Team_member. team_member.rb

  belongs_to :user
  belongs_to :team
  belongs_to :role
end

team.rb

  has_many :team_members
  has_many :users, through: :team_members
  has_many :roles, through: :team_members
end

Solution

  • I assume one user can be part of multiple teams and (obviously) one team has many users, your relation would be roughly like this

    class User < ApplicationRecord
      has_and_belongs_to_many :teams
    end
    
    class Team < ApplicationRecord
      has_and_belongs_to_many :users
    end
    
    

    You are already in right direction but I made little changed to set_current_team and added accessor method to get current team instance.

    class ApplicationController < ActionController::Base
      before_action :authenticate_user!
      before_action :set_current_team
    
      helper_method :current_team
    
      def set_current_team
        return unless session[:current_team]
        session[:current_team] = current_user.teams.first.id
      end
    
      def current_team
        @_team ||= Team.find(session[:current_team])
      end
    end
    

    The current_team method uses memoization technique to cache the current team during the request so that if you call current_team multiple times during a request, it will not call the DB again to get the team record.

    I strongly recommend to read this article 4 Simple Memoization Patterns in Ruby.

    Also notice helper_method macro above the set_current_team which makes this helper method available to your view as well.

    so following will work on your index

    <p><%= current_team %></p>
    

    as well as across all controllers as all controllers inherits from ApplicationController