Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 接受\u嵌套\u属性\u的备选方案-可能是virtus_Ruby On Rails_Ruby_Nested Forms_Nested Attributes - Fatal编程技术网

Ruby on rails 接受\u嵌套\u属性\u的备选方案-可能是virtus

Ruby on rails 接受\u嵌套\u属性\u的备选方案-可能是virtus,ruby-on-rails,ruby,nested-forms,nested-attributes,Ruby On Rails,Ruby,Nested Forms,Nested Attributes,我对rails比较陌生,最终找到了正确的方法来使用accepts\u nested\u attributes\u for 然而,网络上有一些严肃的资源说,使用接受的嵌套属性通常是一种不好的做法(像这样) 为避免接受的_嵌套的_属性_,需要做哪些更改?您会将附加类文件放在哪个文件夹中(我想您需要一个附加类) 我读到这是合适的。是这样吗 下面是一个非常基本的示例,仍然使用接受的嵌套属性(查找完整示例): 型号 class Person < ActiveRecord::Base has

我对rails比较陌生,最终找到了正确的方法来使用
accepts\u nested\u attributes\u for

然而,网络上有一些严肃的资源说,使用
接受
的嵌套属性通常是一种不好的做法(像这样)

为避免
接受
的_嵌套的_属性_,需要做哪些更改?您会将附加类文件放在哪个文件夹中(我想您需要一个附加类)

我读到这是合适的。是这样吗

下面是一个非常基本的示例,仍然使用
接受
的嵌套属性(查找完整示例):

型号

class Person < ActiveRecord::Base

    has_many :phones
    accepts_nested_attributes_for :phones

end

class Phone < ActiveRecord::Base

    belongs_to :person

end
class-Person
控制器

class PeopleController < ApplicationController

    def new

        @person = Person.new
        @person.phones.new

    end

    def create

        @person = Person.new(person_params)
        @person.save

        redirect_to people_path

    end

    def index

        @people = Person.all

    end

private

    def person_params

        params.require(:person).permit(:name, phones_attributes: [ :id, :number ])

    end

end
class PeopleController
查看(people/new.html.erb)





[编辑]

使用服务对象是一个好主意吗?

Railscasts也有一个关于嵌套表单模型的插曲:

如评论所示,cocoon gem简化了很多:

你的问题意味着你认为接受嵌套属性功能是一件坏事,但事实并非如此,而且效果非常好

我首先要说的是,你不需要一个替代方法来接受嵌套的属性,但我会在这篇文章的最后讨论这个问题

关于你提供的链接,它没有提到为什么海报认为接受嵌套属性应该被弃用,而只是声明

依我的拙见,应该反对这种做法

嵌套属性是一个非常重要的概念,当考虑如何以单一形式捕获与父级相关的多个记录时,它不仅是Ruby on Rails的东西,而且在大多数复杂的web应用程序中用于从浏览器将数据发送回服务器,而不考虑用于开发站点的语言

我根本没有批评你指的那篇文章。对我来说,这只是指出了用大量与业务逻辑无关的代码填充数据库支持模型的明显替代方案。所使用的具体示例仅是编码样式首选项备选方案

当时间是金钱,压力是巨大的,一行代码就可以完成任务,而示例中显示的22行代码则是如此。在大多数情况下(并非所有情况下),我的首选是在模型中使用一行代码(接受嵌套属性)来接受从表单发回的嵌套属性

正确回答您的问题是不可能的,因为您实际上没有说明为什么您认为接受\u嵌套的\u属性\u是不好的做法,但是最简单的替代方法是在控制器操作中提取参数散列属性,并在事务中单独处理每条记录

更新-跟进评论

我认为这篇链接文章的作者认为: 在oop范例中,每个对象应该只读取和写入自己的数据。 但是,对于接受嵌套的属性,一个对象会改变某些属性 其他对象数据

好的,让我们澄清一下。 首先,OO范式没有提出这样的问题。类应该是谨慎的,但允许它们与其他类交互。事实上,如果是这样的话,Ruby中的OO方法就没有意义了,因为Ruby中的所有东西都是一个类,因此任何东西都不能与其他任何东西进行对话。想象一下,如果恰好是控制器实例的对象无法与模型或其他控制器交互,会发生什么情况

但是,对于接受嵌套的属性,一个对象会改变某些属性 其他对象数据

关于这句话,我有几点要说,因为它很复杂,所以我会尽量简短

1) 模型实例保护数据。在涉及任何/大多数其他语言(C、Delphi、VB等)的数百个表的非常复杂的场景中,三层解决方案中的中间层就是这样做的。在Rails术语中,模型是业务逻辑的场所,在通常由RDBMS中的存储过程和视图进行备份的3层解决方案中,模型负责中间层的工作。模特们应该能够相互交谈,这是非常正确的

2) 接受的\u嵌套的\u属性\u根本不违反任何OO原则。它只是简化了如果该方法不存在(正如您所发现的)您将需要编写的代码量。如果您接受嵌套在子模型的params散列中的属性,那么您所做的就是允许子模型以与控制器操作相同的方式处理该数据。不绕过任何业务逻辑,您将获得额外的好处

最后

我可以负担得起对代码优雅的关心(比时间更重要)

我可以向您保证,编写超过您需要的20多行代码,并从一个gem中添加数百行代码,其中一行代码就可以为您完成工作,这并不是什么优雅的事情。正如其他人(包括我)所说的,接受\u嵌套的\u属性\u并不总是一个合适的ActiveRecord方法,通过查看不同的方法,最终您将能够更好地判断
<%= form_for @person, do |f| %>
    <p>
        <%= f.label :name %><br />
        <%= f.text_field :name %>
    </p>
    <%= f.fields_for :phones do |builder| %>
    <p>
            <%= builder.label :number %><br />
            <%= builder.text_field :number %>
    </p>
    <% end %>
    <%= f.submit %>
<% end %>
class Contact
  include Virtus

  extend ActiveModel::Naming
  include ActiveModel::Conversion
  include ActiveModel::Validations

  attr_reader :name
  attr_reader :number


  attribute :name, String
  attribute :number, Integer

  def persisted?
    false
  end

  def save
    if valid?
      persist!
      true
    else
      false
    end
  end

private

  def persist!
    @person = Person.create!(name: name)
    @phones = @person.phones.create!(number: number)
  end
end
class ContactsController < ApplicationController

  def new

    @contact = Contact.new

  end

  def create

    @contact = Contact.new(contact_params)
    @contact.save
    redirect_to people_path

  end

  def contact_params

    params.require(:contact).permit(:name, :number)

  end

end
<%= form_for @contact do |f| %>
  <p>
    <%= f.label :name %><br />
    <%= f.text_field :name %>
  </p>

  <p>
    <%= f.label :number %><br />
    <%= f.text_field :number %>
  </p>

  <%= f.submit %>
<% end %>
class ContactListForm
include ActiveModel::Model

attr_accessor :contacts

def contacts_attributes=(attributes)
  @contacts ||= []
  attributes.each do |i, contact_params|
    @contacts.push(Contact.new(contact_params))
  end
end
end

class ContactsController < ApplicationController
   def new
      @contact_list = ContactListForm.new(contacts: [Contact.new])
    end
  end