Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

attributes and constructors in rails

I'm new to rails and don't even know if this is the correct way of solving my situation.

I have a "Club" ActiveRecords model which has a "has_many" association to a "Member" model. I want the logged in "Club" to only be able to administrate it's own "Member" so in the beginning of each action in the "Member" model I did something similar to the following:

def index
 @members = Club.find(session[:club_id]).members

to access the right members. This did not however turn out very DRY as I did the same in every action. So I thought of using something equivalent to what would be called a constructor in other languages. The initialize method as I've understood it. This was however not working, this told me why, and proposed an alternative. The after_initialize.

def after_initialize
 @club = Club.find(session[:club_id])
end

def index
 @members = @club.members
....

does not seem to work anyway. Any pointers to why?

You have a nil object when you didn't expect it!
The error occurred while evaluating nil.members

Makes me think that the @club var isn't set at all.

Also, is this solution really a good one? This makes it hard to implement any kind of "super admin" who can manage the members in all of the clubs. Any ideas on where I am missing something?

like image 504
Felix Andersen Avatar asked Feb 27 '23 20:02

Felix Andersen


1 Answers

You can use a before_filter. Define the filter in your ApplicationController (so that you can access it from any controller).

class ApplicationController < ActionController::Base

  # ..

  protected

    def load_members
      @members = if session[:club_id]
        Club.find(session[:club_id]).members
      else
        []
      end
    end

end

Then, load the filter before any action where you need it. For example

class ClubController < ApplicationController
  before_filter :load_members, :only => %w( index )

  def index
    # here @members is set
  end
end

Otherwise, use lazy loading. You can use the same load_members and call it whenever you need it.

class ClubController < ApplicationController
  def index
    # do something with members
    load_members.each { ... }
  end
end

Of course, you can customize load_member to raise an exception, redirect the client if @members.empty? or do whatever you want.

like image 182
Simone Carletti Avatar answered Mar 07 '23 12:03

Simone Carletti