Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scoping with two foreign keys

I have the following schema: enter image description here

I want to have the option to call proposals for both foreign_keys (author_id and editor_id) as well for separate ones (for example author_proposals and editor_proposals) and I need to have the option to lazy or eager load them (for example User.includes(:proposals) or without it with joins).

Update:

#I have the scopes which is like this:
class User < ActiveRecord::Base
  has_many :author_proposals, class_name: 'Proposal', foreign_key: :author_id
  has_many :editor_proposals, class_name: 'Proposal', foreign_key: :editor_id
end

class Proposal < ActiveRecord::Base
  belongs_to :author, class_name: 'User', foreign_key: :author_id
  belongs_to :editor, class_name: 'User', foreign_key: :editor_id
end

But I need a universal one which it will give me all the proposals (both author_proposals and editor_proposals) which it will also eager load them. Should I use conditions on has_many?

like image 937
JohnDel Avatar asked Apr 10 '15 11:04

JohnDel


3 Answers

I would do something like this:

class User < ActiveRecord::Base
  has_many :authored_proposals, class_name: 'Proposal', foreign_key: :author_id
  has_many :editored_proposals, class_name: 'Proposal', foreign_key: :editor_id

  def proposals
    Proposal.where('author_id = :id OR editor_id = :id', { id: id }).distinct
  end
end

class Proposal < ActiveRecord::Base
  belongs_to :author, class_name: 'User', foreign_key: :author_id
  belongs_to :editor, class_name: 'User', foreign_key: :editor_id

  def users
    User.where(id: [author_id, editor_id].uniq)
  end
end
like image 103
spickermann Avatar answered Nov 13 '22 17:11

spickermann


You can do something like:

class User < ActiveRecord::Base
  has_many :authored_proposals, class_name: 'Proposal', foreign_key: :author_id
  has_many :editored_proposals, class_name: 'Proposal', foreign_key: :editor_id

  def proposals
    authored_proposals | editored_proposals
  end
end

class Proposal < ActiveRecord::Base
  belongs_to :author, class_name: 'User', foreign_key: :author_id
  belongs_to :editor, class_name: 'User', foreign_key: :editor_id

  def users
    author | editor
  end
end

You can eager load proposals by doing: User.includes(:authored_proposals, :editored_proposals). This is not pure rails way, but seems cleaner to me.



You can also do :

class User < ActiveRecord::Base
  has_many :authored_proposals, class_name: 'Proposal', foreign_key: :author_id
  has_many :editored_proposals, class_name: 'Proposal', foreign_key: :editor_id

  has_many : proposals, finder_sql: proc { "SELECT * FROM proposals WHERE (proposals.author_id = #{id} or proposals. editor_id = #{id})" }
end
like image 6
Saurabh Avatar answered Nov 13 '22 17:11

Saurabh


Set your associations like this:

class User < ActiveRecord::Base
  has_many :author_proposals, :class_name => "Proposal", :foreign_key => "author_id"
  has_many :editor_proposals, :class_name => "Proposal", :foreign_key => "editor_id"
end

class Proposal < ActiveRecord::Base
  belongs_to :author, :class_name => 'User', :foreign_key => "author_id"
  belongs_to :editor, :class_name => 'User', :foreign_key => "editor_id"
end
like image 1
RAJ Avatar answered Nov 13 '22 17:11

RAJ