在其父模型的视图上创建嵌套的模型实例(has_many关系) [英] Creating a nested model instance (has_many relation) on the view of its parent model

查看:60
本文介绍了在其父模型的视图上创建嵌套的模型实例(has_many关系)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个模型A和一个模型B,关系是A has_many B(并且B属于A).我有一个模型,一个控制器和A的视图,而只有B的模型.我想在A(url/a/1/edit)的编辑视图上创建和编辑B的实例.

我知道我可以为B创建一个控制器并在A的视图中使用表单来调用这些方法,但是随后我需要重定向回A的视图,因为我不希望B的实际视图./p>

有推荐的方法吗?我想要的是不破坏任何Rails提供的帮助程序(例如,在转发后,我认为获得错误消息和类似的东西很痛苦).

提前谢谢!

解决方案

在模型级别,您将使用 accepts_nested_attributes_for .

  A类<应用模型has_many:bsaccepts_nested_attributes_for:bsvalidates_associated:bs结尾B级应用模型当属:a结尾 

这使A可以获取属性并通过将属性 bs_attributes 传递给属性数组来创建嵌套的 bs . validates_associated 可以用来确保 bs 的A不能持续存在也是无效的.

要创建嵌套表格字段,请使用白名单嵌套属性,请使用带有允许数组的哈希键子记录的属性:

  params.require(:a).permit(:foo,bs_attributes:[:id,:bar]) 

在创建新记录时,如果希望存在用于创建嵌套记录的输入,还必须填充"表单:

 类AsController<应用程序控制器def新@a = A.newseed_form结尾def创建@a = A.new(a_params)如果@ a.saveredirect_to @a别的seed_form渲染:new结尾结尾def更新如果@ a.update(a_params)redirect_to @a别的渲染:edit结尾结尾私人的def seed_form5.times {@ a.bs.new}如果@ a.bs.none?结尾def a_paramsparams.require(:a).permit(:foo,bs_attributes:[:id,:bar])结尾结尾 

修改:seed_form也可以只添加一个,然后每次都这样做.因此,您将始终要添加一个空"项.如果未填空,则需要确保将空的过滤掉,方法是将 accepts_nested_attributes_for 更改为:

  accepts_nested_attributes_for:bs,reject_if:proc {| attr |attr ['bar'].blank?} 

I have a model A und a model B and the relation is A has_many B (and B belongs_to A). I have a model, a controller and views for A and only a model for B. I want to create and edit the instances of B on the edit view of A ( url/a/1/edit).

I know I can create a controller for B and call those methods using a form in the view of A, but then I need to redirect back to the view of A, because I don't want actual views for B.

Is there a recommended way to do this? What I want is to not break any of the helpers rails provides (e.g. after a forward I think it's a pain to get error messages and stuff like that).

Thanks in advance!

解决方案

On the model level you would use accepts_nested_attributes_for.

class A < ApplicationModel
  has_many :bs
  accepts_nested_attributes_for :bs
  validates_associated :bs
end

class B < ApplicationModel
  belongs_to :a
end

This lets A take attributes and create nested bs by passing the attribute bs_attributes with an array of attributes. validates_associated can be used to ensure that A cannot be persisted of the bs are not also valid.

To create the nested form fields use fields_for

<%= form_for(@a) do |f| %>
  # field on A
  <%= f.text_input :foo %>
  # creates a fields for each B associated with A.
  <%= f.fields_for(:bs) do |b| %>
    <%= b.text_input :bar %>
  <% end %>
<% end %>

To whitelist nested attributes use a hash key with an array of permitted attributes for the child records:

params.require(:a)
      .permit(:foo, bs_attributes: [:id, :bar])

When creating new records you also have to "seed" the form if you want there to be inputs present for creating nested records:

class AsController < ApplicationController

  def new
    @a = A.new
    seed_form
  end

  def create
    @a = A.new(a_params)
    if @a.save 
      redirect_to @a
    else
      seed_form
      render :new
    end
  end

  def update
    if @a.update(a_params) 
      redirect_to @a
    else
      render :edit
    end
  end

  private

  def seed_form
    5.times { @a.bs.new } if @a.bs.none?
  end

  def a_params
    params.require(:a)
          .permit(:foo, bs_attributes: [:id, :bar])
  end
end

Edit: seed_form can also just add one and do that every time. So you will always have one "empty" one to add. You need to make sure to filter out the empty one before saving if it was not filled by changing the accepts_nested_attributes_for to:

accepts_nested_attributes_for :bs, reject_if: proc { |attr| attr['bar'].blank? }

这篇关于在其父模型的视图上创建嵌套的模型实例(has_many关系)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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