Rails has_many:通过关联:将实例保存到联接表中 [英] Rails has_many :through association: save instance into join table
问题描述
在我们的Rails应用程序中,有3种型号:
In our Rails app, there are 3 models:
class User < ActiveRecord::Base
has_many :administrations, dependent: :destroy
has_many :calendars, through: :administrations
end
class Administration < ActiveRecord::Base
belongs_to :user
belongs_to :calendar
end
class Calendar < ActiveRecord::Base
has_many :administrations, dependent: :destroy
has_many :users, through: :administrations
end
以下是相应的迁移:
class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.string :first_name
t.string :last_name
t.string :email
t.timestamps null: false
end
end
end
class CreateAdministrations < ActiveRecord::Migration
def change
create_table :administrations do |t|
t.references :user, index: true, foreign_key: true
t.references :calendar, index: true, foreign_key: true
t.string :role
t.timestamps null: false
end
end
end
class CreateCalendars < ActiveRecord::Migration
def change
create_table :calendars do |t|
t.string :name
t.timestamps null: false
end
end
end
我们创建了calendar#create
动作,如下所示:
We have created the calendar#create
action as follows:
def create
@calendar = current_user.calendars.build(calendar_params)
if @calendar.save
flash[:success] = "Calendar created!"
redirect_to root_url
else
render 'static_pages/home'
end
end
以及相应的_calendar_form.html.erb
部分:
<%= form_for(@calendar) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="field">
<%= f.text_field :name, placeholder: "Your new calendar name" %>
</div>
<%= f.submit "Post", class: "btn btn-primary" %>
<% end %>
之所以如此有效",是因为当我们通过表单创建新日历时,当您键入Calendar.all
时,它确实会显示在Rails控制台中.
This "works" since, when we create a new calendar through the form, it does show up in Rails console, when we type Calendar.all
.
但是,似乎没有创建新的@administration
并且未更新Administration表,因为当我们在控制台中键入Administration.all
时,什么也没有返回.
However, it seems like no new @administration
is being created and the Administration table is not updated, as nothing returns when we type Administration.all
in the console.
我们认为,管理表(即用户表和日历表之间的联接表,分别包含user_id
和calendar_id
列)在创建新日历时会自动更新.
We thought the Administration table, which is the join table between the User table and the Calendar table, and which respectively contains user_id
and calendar_id
columns, would be updated automatically when creating a new calendar.
我们如何实现这一目标?我们是否需要创建特定的administration#create
操作?
How can we achieve this? Do we need to create a specific administration#create
action?
更新:根据评论和答案,我们实现了以下CalendarsController
:
UPDATE: based on the comments and the answers, we implemented the following CalendarsController
:
class CalendarsController < ApplicationController
def create
@calendar = current_user.calendars.build(calendar_params)
if @calendar.save
current_user.administrations << @calendar
@calendar.administration.role = 'creator'
flash[:success] = "Calendar created!"
redirect_to root_url
else
render 'static_pages/home'
end
end
...
但是,这将返回以下错误:
However, this returns the following error:
ActiveRecord::AssociationTypeMismatch in CalendarsController#create
unless record.is_a?(reflection.klass) || record.is_a?(reflection.class_name.constantize)
message = "#{reflection.class_name}(##{reflection.klass.object_id}) expected, got #{record.class}(##{record.class.object_id})"
raise ActiveRecord::AssociationTypeMismatch, message
end
end
app/controllers/calendars_controller.rb:6:in `create'
我们错过了什么吗?
推荐答案
如果使用current_user.calendars.build(calendar_params),则只会获得新的日历,而无法进行管理.
If you use current_user.calendars.build(calendar_params), you will only get new calendar, no administration.
如果使用current_user.calendars.create(calendar_params),则将管理和日历都保存到数据库中.
If you use current_user.calendars.create(calendar_params), you will get both administration and calendar saved into database.
如果要先检查日历是否成功保存,请使用以下方法:
If you want to check whether calendar is successfully saved first, I use this approach:
def create
@calendar = Calendar.build(calendar_params)
if @calendar.save
current_user.administrations << @calendar
flash[:success] = "Calendar created!"
redirect_to root_url
else
render 'static_pages/home'
end
end
已更新:
将日历与用户相关联时出错.这应该是正确的:
There is an error to associate calendar to user. This should be the correct one:
def create
@calendar = current_user.calendars.build(calendar_params)
if @calendar.save
current_user.calendars << @calendar
flash[:success] = "Calendar created!"
redirect_to root_url
else
render 'static_pages/home'
end
end
这篇关于Rails has_many:通过关联:将实例保存到联接表中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!