TimKaechele
TimKaechele

Reputation: 530

Rails Association if boolean is true

I have two models, an user model and a course model

The user schema looks like this:

create_table "users", force: true do |t|
    t.string   "username",                        default: "",    null: false
    t.string   "first_name",                      default: "",    null: false
    t.string   "last_name",                       default: "",    null: false
    t.string   "password_digest",                 default: "",    null: false
    t.string   "email",                           default: "",    null: false
    t.string   "email_unconfirmed",               default: "",    null: false
    t.string   "email_verification_token",        default: "",    null: false
    t.string   "password_reset_token",            default: "",    null: false
    t.datetime "password_reset_token_expires_at"
    t.boolean  "admin",                           default: false
    t.boolean  "teacher",                         default: false
    t.datetime "created_at"
    t.datetime "updated_at"
end

The course schema looks like this:

create_table "courses", force: true do |t|
    t.integer  "teacher_id"
    t.string   "name"
    t.text     "description"
    t.datetime "created_at"
    t.datetime "updated_at"
end

And the user model:

class User < ActiveRecord::Base
    has_many :taught_courses, :foreign_key => :teacher_id 
end

I only want to have users where the teacher/admin boolean is true to have taught_courses but as far as I know you can't wrap the association in an if statement, cause the teacher?/admin? method is not available so how do I handle this?

Upvotes: 2

Views: 1594

Answers (1)

Richard Peck
Richard Peck

Reputation: 76774

I think you can do this:

class User < ActiveRecord::Base
    has_many :taught_courses, -> { where(admin: true, teacher: true)}, :foreign_key => :teacher_id 
end

You can read up more about ActiveRecord Conditional Associations online, and see an example here:

4.1.3.1 where

The where method lets you specify the conditions that the associated object must meet.

class Order < ActiveRecord::Base
  belongs_to :customer, -> { where active: true }
end

Update

If you're going to use another model for verification, you may want to use .joins. However, considering you're pinging the original model, you may wish to use ActiveRecord Association Extensions

These give you access to the proxy_association objects, which give you the ability to access the "parent" data through memory:

class User < ActiveRecord::Base
    has_many :taught_courses, :foreign_key => :teacher_id do
        def admins_and_teachers
            user = proxy_association.owner
            where("users.admin = ? AND users.teacher = ?", user.admin, user.teacher)
        end
    end
end

I think this will work; if not, it will definitely be the path I'd look at

Upvotes: 6

Related Questions