Rails has_many:通过关联:将实例保存到联接表中 [英] Rails has_many :through association: save instance into join table

查看:69
本文介绍了Rails has_many:通过关联:将实例保存到联接表中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我们的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_idcalendar_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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆