has_many through problem


I have pretty generic user/role models linked through an Authorization model using has_many :through => … but I’m having difficulty getting it to work the way I expect it to. When I instantiate a new role I can see it’s attributes via to_yaml(), but when I call it’s name() method I get nil. I’m baffled; below is a short code snippet - can anyone see what the problem is?

class Authorization < ActiveRecord::Base belongs_to :user belongs_to :role end

class Role < ActiveRecord::Base has_many :authorizations has_many :users, :through => :authorizations attr_accessor :id, :name, :description DEFAULT = 4 end

class User < ActiveRecord::Base has_many :authorizations has_many :roles, :through => :authorizations attr_accessible :id, :sso_id, :first_name, :last_name, :email

def self.get_or_create_from_sso_user(sso_user) user = self.find_by_sso_id(sso_user.id) if user return user else # Create user created_user = self.create( :sso_id => sso_user.id, :first_name => sso_user.first_name, :last_name => sso_user.last_name, :email => sso_user.email ) Authorization.create! :user_id => created_user.id, :role_id => Role::DEFAULT created_user.reload created_user.save! end end

def has_admin_role? self.roles.each do |role| puts role.to_yaml # see the output for this below puts role.name # see the output for this below return true if role.name.eql? ‘admin’ end return false end

def sso_user @sso_user ||= SSO::User.find(self.id) end end

The output for the two puts() above gives me this: – begin – — !ruby/object:Role attributes: name: requester updated_at: id: “4” description: Default role for all JGI users created_at: attributes_cache: {}

nil – end –

I also seem to have a problem with the role class itself:


role = Role.find_by_id(1) => #<Role id: 1, name: “admin”, description: “Administrator (global read/write privileges)”, created_at: nil, updated_at: nil> role.name => nil

Creating roles is also an issue… I’m baffled!

=> #<Role id: nil, name: nil, description: nil, created_at: nil, updated_at: nil>

role.name = ‘test’ => “test” role.save! => true role => #<Role name: nil, description: nil, created_at: “2009-07-02 13:04:44”, updated_at: “2009-07-02 13:04:44”>

Here’s my migration:

require ‘active_record/fixtures’

class CreateRoles < ActiveRecord::Migration def self.up create_table :roles do |t| t.string :name t.string :description t.timestamps end

Fixtures.create_fixtures('db/fixtures', File.basename("roles.yml", '.*'))


def self.down drop_table :roles end end