如何更改 has_through rails 关联的方法名称?

How to change method name for has_through rails association?

我正在尝试创建两个与相同目标表有很多关系,但我无法覆盖 rails 在定义关联时创建的默认方法名称。

情况如下:

class User < ApplicationRecord
  has_many :conference_attendees, dependent: :destroy
  has_many :conference_organizers, dependent: :destroy
  has_many :conferences, through: :conference_attendees, class_name: 'attending', dependent: :destroy
  has_many :conferences, through: :conference_organizers, source: :conference, dependent: :destroy

class ConferenceOrganizer < ApplicationRecord
  alias_attribute :organizers, :users
  belongs_to :conference
  belongs_to :user
end

class ConferenceAttendee < ApplicationRecord
  belongs_to :conference
  belongs_to :user
end

class Conference < ApplicationRecord
  has_many :conference_attendees, dependent: :destroy
  has_many :conference_organizers, dependent: :destroy
  has_many :users, through: :conference_attendees, dependent: :destroy
  has_many :organizers, through: :conference_organizers, source: :user, dependent: :destroy

我正在尝试访问用户参加的所有会议,然后是用户使用以下内容组织的所有会议:

User.find(id: <id>).organizing
User.find(id: <id>).attending

但我不能

User.find(id: <id>).conferences

默认组织会议。如何访问参加会议?

如果你想在用户和会议上加入两个table,你可以这样设置。

# app/models/user.rb
has_many :conference_attendees, dependent: :destroy
has_many :conference_organizers, dependent: :destroy
has_many :attending, through: :conference_attendees, source: :conference
has_many :organizing, through: :conference_organizers, source: :conference

# app/models/conference.rb
has_many :conference_attendees, dependent: :destroy
has_many :conference_organizers, dependent: :destroy
has_many :attendees, through: :conference_attendees, source: :user
has_many :organizers, through: :conference_organizers, source: :user

# app/models/conference_attendee.rb
belongs_to :user
belongs_to :conference

# app/models/conference_organizer.rb
belongs_to :user
belongs_to :conference

然后在会议展示页面上展示与会者和组织者:

# app/controllers/conferences_controller.rb
def show
  @conference = Conference.find(params[:id])
  @attendees = @conference.attendees
  @organizers = @conference.organizers
end

# app/views/conferences/show.html.erb
<h3>Organizers</h3>
<% @organizers.each do |user| %>
  <li><%= user.name %></li>
<% end %>
<h3>Attendees</h3>
<% @attendees.each do |user| %>
  <li><%= user.name %></li>
<% end %>

然后在用户的展示页面展示会议:

# app/controllers/users_controller.rb
def show
  @user = User.find(params[:id])
  @attending = @user.attending
  @organizing = @user.organizing    
end

# app/views/users/show.html.erb
<h3>Conferences Organizing</h3>
<% @organizing.each do |conference| %>
  <li><%= link_to(conference.name, conference) %><br> Date: <%= conference.date %></li>
<% end %>
<h3>Conferences Attending</h3>
<% @attending.each do |conference| %>
  <li><%= link_to(conference.name, conference) %><br> Date: <%= conference.date %></li>
<% end %>

话虽这么说,使用一个连接 table 比使用两个连接可能更干净。我会把它放在一个单独的答案中。

由于您是在相同的两个 table 上进行联接,因此进行一次联接 table 并添加一个名为 status 的字段以区分组织者和与会者可能会更清晰。这样您就可以添加其他状态值,例如 "presenter"。

设置tablerails g model Registration user:references conference:references status:stringrake db:migrate

设置模型关联:

# app/models/user.rb
has_many :registrations, dependent: :destroy

# app/models/conference.rb
has_many :registrations, dependent: :destroy

# app/models/registration.rb
belongs_to :user
belongs_to :conference
scope :attendees, -> { where( status: "Attendee") }
scope :organizers, -> { where( status: "Organizer") }

然后在会议展示页面上展示与会者和组织者:

# app/controllers/conferences_controller.rb
def show
  @conference = Conference.find(params[:id])
  @attendee_registrations = @conference.registrations.attendees
  @organizer_registrations = @conference.registrations.organizers
end

# app/views/conferences/show.html.erb
<h3>Organizers</h3>
<% @organizer_registrations.each do |registration| %>
  <li><%= link_to(registration.user.name, registration.user) %></li>
<% end %>
<h3>Attendees</h3>
<% @attendee_registrations.each do |registration| %>
  <li><%= link_to(registration.user.name, registration.user) %></li>
<% end %>

然后在用户的展示页面展示会议:

# app/controllers/users_controller.rb
def show
  @user = User.find(params[:id])
  @attending_registrations = @user.registrations.attendees
  @organizing_registrations = @user.registrations.organizers   
end

# app/views/users/show.html.erb
<h3>Conferences Organizing</h3>
<% @organizing_registrations.each do |registration| %>
  <li><%= link_to(registration.conference.name, registration.conference) %><br> 
  Date: <%= registration.conference.date %></li>
<% end %>
<h3>Conferences Attending</h3>
<% @attending_registrations.each do |registration| %>
  <li><%= link_to(registration.conference.name, registration.conference) %><br> 
  Date: <%= registration.conference.date %></li>
<% end %>