Junaid Farooq
Junaid Farooq

Reputation: 2608

Rails column association with integer array

I have 2 models, User and Email, As it's clear a user will have an email, as sender and recipient.

In User model

  has_many :sent_emails, class_name: "Email", foreign_key: "sender_id"
  has_many :received_emails, class_name: "Email", foreign_key: "recipient_id"

and in Email model

  belongs_to :sender, class_name: "User", primary_key: "id"
  belongs_to :recipient, class_name: "User", primary_key: "id"

That's how am getting associations, That's was for information only, The problem is: I have other 2 columns as cc and bcc as

add_column :emails, :cc, :integer, default: [], array: true
add_column :emails, :bcc, :integer, default: [], array: true

I want to make associations between email and user on those columns as well.

So That if I add,

 => #<Email id: nil, sender_id: 5, recipient_id: 10, body: "Hello its first email.", subject: "Hello Hello", state: 1, head: nil, tail: nil, created_at: nil, updated_at: nil, cc: [9, 8], bcc: [4,19]>

As I can do Email.first.sender or Email.first.recipient I can get the user, So that I may do Email.first.cc or Email.first.bcc I can get the users.

As I can do User.first.sent_emails and User.first.received_emails, I can get User.first.cc_mails or User.first.bcc_mails?

Is that possible to build association like that?

Upvotes: 1

Views: 1483

Answers (2)

azarkon
azarkon

Reputation: 78

The more idiomatic rails way to build this sort of relationship to use the has_and_belongs_to_many or has_many :through association:

http://guides.rubyonrails.org/association_basics.html#the-has-and-belongs-to-many-association

This will use a pivot table instead of an integer array in the database. The documentation (linked to above) describes how to create the database schema for this.

You can then define the association on your user model something like:

has_many :ccs has_many :ccd_emails, through: :ccs

Using this schema and these associations, ActiveRecord will give you the functions you want built in, including User#ccd_emails and User#ccd_email_ids which will give you array-like representations of User instances or integers ids respectively.

This also has the advantage that it is 100% portable to different databases.

Upvotes: 1

Ilya Lavrov
Ilya Lavrov

Reputation: 2860

Unfortunately Rails does not support has_many relation for this kind of structure. But you can make manual methods cc_emails and bcc_emails:

class User < ActiveRecord::Base
  ...

  def cc_mails
    Email.where("? = ANY (cc)", id)
  end

  def bcc_mails
    Email.where("? = ANY (bcc)", id)
  end
end

Upvotes: 1

Related Questions