0

I want to do STI in Rails.

class AbstractUser < ActiveRecord::Base
  self.table_name = 'users'

  belongs_to :organization, :inverse_of => :users

  # reporter user
  has_many  :requests, :dependent => :destroy

  # startup user
  has_many  :responses, :dependent => :destroy
  has_many  :startup_requests, :through => :responses, :source => :request

  scope :reporters, where(:type => 'Reporter')
  scope :startup_employees, where(:type => 'Startup')
  scope :on_waitlist, where(:waitlist => true)
  scope :not_on_waitlist, where(:waitlist => false)

end

require 'rfc822'

class User < AbstractUser
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :confirmable

  validates :name, :presence => true
  validates :surname, :presence => true
  validates :title, :presence => true
  validates :password, :presence => true, :length => { :minimum => 8 }
  validates :email, :presence => true, :format => { :with => RFC822::EMAIL_REGEXP_WHOLE }

  attr_accessible :name, :surname, :title, :organization,
                  :email, :password, :fullname
end

require 'rfc822'

class UserForAdmin < AbstractUser
  validates :email, :presence => true, :format => { :with => RFC822::EMAIL_REGEXP_WHOLE }
  validates :organization_id, :presence => true

  attr_accessible :name, :surname, :title, :organization, :email,
                  :password, :fullname, :password_confirmation, :type, 
                  :organization_id, :waitlist, :invitation_token
end

And there is some problem with these scopes.

Couldn't find UserForAdmin with id=7 [WHERE "users"."type" IN ('UserForAdmin') AND "users"."waitlist" = 'f']

I also tried to put these scopes in UserForAdmin instead of AbstractUser with the same result. I (probably) need scopes instead of custom methods, because I use them in ActiveAdmin. How can I solve this?

ciembor
  • 7,189
  • 13
  • 59
  • 100
  • What are the conditions for the error occurring? Which scope are you calling? What do you expect to see? – Jon Cairns May 22 '13 at 12:00
  • It occurs when I try to `if UserForAdmin.not_on_waitlist.find(params[:id])` in ActiveAdmin's controller. – ciembor May 22 '13 at 12:09
  • Is the query that it's attempting to do wrong? Looks like it's doing what you've asked it to do, so you need to say what you expect it do. – Jon Cairns May 22 '13 at 12:13
  • I expected just `SELECT "users".* WHERE "users"."waitlist" = 'f' FROM "users" ` – ciembor May 22 '13 at 12:29
  • I see. But isn't that removing the value of STI? Don't you actually want the type to be in the select, otherwise there would be no point in doing the query through the `UserForAdmin` class? – Jon Cairns May 22 '13 at 12:41
  • Yeah, previously I tried to use two classes and a mixin, but I hit a wall: http://stackoverflow.com/questions/16688257/separating-attr-accessible-using-two-different-models-with-the-same-table. I belived it may work with third class, but as I see I misunderstood the Rails convention. – ciembor May 22 '13 at 12:44

1 Answers1

1

If you don't want to receive all users, you need to query with the base class. In a simpler example:

class Animal < ActiveRecord::Base
end

class Dog < Animal
end

class Cat < Animal
end

Dog.create
Cat.create

Animal.all
=> [dog, cat]

Dog.all
=> [dog]

Cat.all
=> [cat]

So, in your case, you'd want to:

AbstractUser.not_on_waitlist.find(params[:id])

If this user is a UserForAdmin you'll receive an object of class UserForAdmin. If it's just a user, you'll receive an object of class User

Jesse Wolgamott
  • 40,197
  • 4
  • 83
  • 109