正在创建模型 relationships/Nested 资源

Creating model relationships/Nested resourses

您好,我正在尝试在我添加的两个模型 Establishments 和 OpenClosed 之间建立关系

class Establishment < ApplicationRecord
  has_many :open_closed
end

class OpenClosed < ApplicationRecord
  belongs_to :establishment
end

我已将 establishment_id 字段添加到 open_closed table,然后是 运行 rails db:migrate。接下来我嵌套了资源

resources :establishments do
  resources :open_closeds
end 

然后我修改了 OpenClosed 控制器 #new line 注释,我在其中添加了新代码

def new
 @establishment = Establishment.find(params[:establishment_id]) #new line added
 @open_closed = OpenClosed.new
end

 # GET /open_closeds/1/edit
def edit
end

# POST /open_closeds
# POST /open_closeds.json
def create
 @establishment = Establishment.find(params[:establishment_id]) #new line added
 @open_closed = OpenClosed.new(open_closed_params)
 @open_closed.Establishment = @establishments #new line added

respond_to do |format|
  if @open_closed.save
    format.html { redirect_to @open_closed, notice: 'Open closed was       successfully created.' }
    format.json { render :show, status: :created, location: @open_closed }
  else
    format.html { render :new }
    format.json { render json: @open_closed.errors, status: :unprocessable_entity }
  end
 end
end

这是我在 open_closed 视图中提交表单时遇到的错误:

undefined method `Establishment=' for # 你是说吗? establishment= 建立 establishment_id= establishment_id establishment_id?

我这辈子都无法弄清楚哪里出了问题,有人可以用这个为我指明正确的方向,非常感谢。

您需要像这样更改您的代码:

@open_closed = @establishment.open_closeds.new(open_closed_params)

所以它会为你分配@open_closed.establishment_id。

您似乎还需要将 has_many :open_closed 更改为 has_many :open_closeds

@open_closed.Establishment = @establishments #new line added

这是失败的行。 那应该是:

@open_closed.establishment = @establishment #new line added

请注意,大写很重要。您的关联对象永远不会以大写字母开头 - 大写字母用于 class 名称(例如,当您定义 Establishment 模型时)或常量(您在此处未使用)。

另请注意,您有错字 -> @establishment 不是复数(只有一个):)

首先,将 OpenClosed#new 操作重写为如下所示:

<h1>New Open Closed</h1>

<%= render 'form', establishment: @establishment, open_closed: @open_closed %>
<%= link_to 'Back', establishment_open_closeds_path %>

这意味着我们现在将一个 Establishment 对象和一个 OpenClosed 对象传递给部分形式。

接下来,更改

处的 <%= form_for ... %> 声明
`app/views/open_closeds/_form.html.erb`

看起来像这样:

<%= form_for [establishment, open_closed] do |f| %>

我们刚刚告诉我们的表单使用 EstablishmentOpenClosed 对象。

接下来,重写 open_closed 控制器,使其看起来像这样:

def create
  @establishment = Establishment.find(params[:establishment_id])
  @open_closed = OpenClosed.new(open_closed_params)
  @open_closed.Establishment = @establishment #new line added

  respond_to do |format|
    if @open_closed.save
      format.html { redirect_to [@establishment, @open_closed], notice: 'Open closed was successfully created.' }
      format.json { render :show, status: :created, location: @open_closed }
    else
      format.html { render :new }
      format.json { render json: @open_closed.errors, status: :unprocessable_entity }
    end
  end
end

我做的两个修改是:

换行

@open_closed.Establishment = @establishments

@open_closed.establishment = @establishment

请注意,establishment 中的 'e' 现在是小写的,我删除了该行末尾的 's'(这可能只是一个拼写错误)。如果您查看 db/schema.rb 文件,您应该会看到

t.integer  "establishment_id"

open_closedstable。在 ActiveRecord 中,您使用与数据库 table 中的行相同的名称访问 class 的方法。然而,对于像 establishment_id 这样的外键,rails 足够聪明,知道当你说 @open_closed.establishment 时,你实际上只想要属于你的 OpenClosedEstablishment ] 对象。

我在上面的代码中更改的第二件事是这一行:

redirect_to [@establishment, @open_closed] ...    

您需要同时提供建立和 open_closed 对象才能使路由有效。由于重定向语句将您发送到 OpenClosed class 的显示方法,您可以 运行 搜索路由以查看 OpenClosed#show 的路由是什么样的。我在你的路由文件中 运行 rake routes 并为 OpenClosed

的显示方法得到了这个
establishment_open_closed GET    /establishments/:establishment_id/open_closeds/:id(.:format)      open_closeds#show

因此您可以看到 OpenClosed#show 需要 Establishment 对象和 OpenClosed 对象。您只需要在数组中提供两个对象作为 redirect_to

的第一个参数

注意:

尝试此操作时,您可能仍会遇到错误,因为应用程序中的许多路由都不正确,需要更改。例如,要实际呈现 OpenClosed#show 视图(成功调用 OpenClosed#create 后重定向到的地方),您需要对 OpenClosed 控制器的显示模板进行以下修改:

<p id="notice"><%= notice %></p>

<%= link_to 'Edit', edit_establishment_open_closed_path(@open_closed) %> |
<%= link_to 'Back', establishment_open_closeds_path %>

作为对未来的提示,您可以添加

<%= debug(params) if Rails.env.development? %> 在你的 app/views/layouts/application.html.erb 文件中直接在 yield 之后。这将打印出在调试时有用的服务器响应信息。

最后,您的应用程序的其他部分在您修复路由之前将无法运行,但希望您现在有足够的信息来执行此操作。

有关嵌套路由的更多信息,请查看 official rails guids

编码愉快!