创建模型关系/嵌套资源

时间:2016-10-18 22:31:10

标签: ruby-on-rails nested-resources

您好我正在尝试在两个模型之间建立关系。我已经添加了

两个模型和OpenClosed
class Establishment < ApplicationRecord
  has_many :open_closed
end

class OpenClosed < ApplicationRecord
  belongs_to :establishment
end

我已将establish_id字段添加到open_closed表中,然后运行rails db:migrate.Next我已嵌套资源

resources :establishments do
  resources :open_closeds
end 

然后我修改了OpenClosed控制器#new line comment我添加了新代码

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视图中提交表单时遇到的错误:

未定义的方法`Establishment ='for#您的意思是? establishment = establishment establishment_id = establishment_id establishment_id?

不能为我的生活找到我在哪里出错的地方,有人可以请我指出正确的方向,并提前多谢这个。

3 个答案:

答案 0 :(得分:0)

您需要更改代码:

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

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

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

答案 1 :(得分:0)

@open_closed.Establishment = @establishments #new line added

这是失败的路线。 那应该是:

@open_closed.establishment = @establishment #new line added

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

另请注意,您有拼写错误 - &gt; @establishment不是复数(只有一个):)

答案 2 :(得分:0)

首先,将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

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

t.integer  "establishment_id"

open_closeds表下。在ActiveRecord中,使用与数据库表中的行相同的名称访问类的方法。但是,对于像establishment_id这样的外键,rails很聪明,知道当你说@open_closed.establishment时,你真的只想要属于你的Establishment对象的OpenClosed

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

redirect_to [@establishment, @open_closed] ...    

您需要同时提供establishment和open_closed对象才能使路由有效。由于redirect语句将您发送到OpenClosed类的show方法,因此您可以运行rake路由以查看OpenClosed#show的路由。我在您的路径文件上运行了rake routes并获得了OpenClosed的show方法

establishment_open_closed GET    /establishments/:establishment_id/open_closeds/:id(.:format)      open_closeds#show

因此,您可以看到OpenClosed#show期望建立对象和OpenClosed对象。您只需要将数组中的两个对象都作为redirect_to

的第一个参数提供

注意:

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

<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。这将打印出服务器响应信息,这些信息在调试时很有用。

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

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

Happing coding!