【问题标题】:How to use nested forms in Rails if the fields have the same name?如果字段名称相同,如何在 Rails 中使用嵌套表单?
【发布时间】:2020-11-08 10:01:06
【问题描述】:

我有两个模型,狗和主人,我希望他们的名字相同,如果我要求填写两次字段(一次是狗,另一次是主人),那将是多余的。我想知道是否有一种更简单的方法可以用一个输入更新两个数据库。

<h1>Create a new Dog:</h1>
<%= form_for(@dog) do |f|%>
  <div>
    <%= f.label :name%>
    <%= f.text_field :name%>
  </div><br>
    
  <div>
    <%= f.label :breed%>
    <%= f.text_field :breed%>
  </div><br>
    
  <div>
    <%= f.label :age%>
    <%= f.text_field :age%>
  </div><br>
    
  <div>
    <h3>create a new owner:</h3>
    <%= f.fields_for :owner, Owner.new do |owner_attributes|%>
        <%= owner_attributes.label :name, "Owner Name:" %>
        <%= owner_attributes.text_field :name %>
    <% end %>
  </div>
    
  <%= f.submit %>
    
<% end %>

【问题讨论】:

    标签: ruby-on-rails ruby forms form-for accepts-nested-attributes


    【解决方案1】:

    首先,不知道为什么要保持主人和狗的名字相同。

    但是,有很多方法可以实现您想要的:

    1. 您可以简单地从表单中省略所有者名称。

    所以你不再需要:&lt;%= owner_attributes.label :name, "Owner Name:" %&gt; 或者您不再需要:

    <div>
        <%= f.label :name%>
        <%= f.text_field :name%>
      </div><br>
    

    在 Owner/Dog 模型中,您可以在回调中传递狗/所有者的名称 - 可能是 after_initialize 或 before_save 或 before_validation,具体取决于您的验证要求。

    class Dog
      belongs_to :owner
      before_validation :set_name
    
      private
    
      def set_name
        self.name = owner&.name
      end
    end
    
    1. 您可以改为将所有者名称设置为隐藏字段,并可以编写一些 javascript 在提交表单或onblur 事件之前使用狗名更新隐藏字段。我更喜欢第一种方法,因为它比保持数据库一致性的 JS 解决方案更简单、更安全

    【讨论】:

    • 感谢您的回答!我有一个问题(我是 Rails 新手): self.name = owner.name 究竟是如何工作的?我的控制器有一个def new,其中@dog = Dog.new@dog.build_owner。我假设在提交表单后,@dog@dog.build_owner 之间会自动创建一个关联,这最终会调用调用 set_name 的 Dog 类中的 before_validation。这个跟踪正确吗?
    • 另外,owner&amp;.name 中的 & 是您的答案中的错字吗?如果没有,将不胜感激学习功能的帮助!
    【解决方案2】:

    如果狗belongs_to和主人,你真的不需要单独存储主人的名字。您可以在任何有Dog 实例的地方调用dog.owner.name。话虽如此,使用.merge() 在控制器中的 POSTed 表单值之上附加属性相对简单:

    def create
      @dog = Dog.new(dog_params.merge(owner: params[:dog][:owner])[:name])
      if @dog.save
        ...
      end
    end
    
    def dog_params
      params.require(:dog).permit(:name, :breed, :age, owner: %i[name])
    end
    

    【讨论】:

      猜你喜欢
      • 2021-04-28
      • 2021-06-08
      • 2016-09-28
      • 2020-12-23
      • 2012-05-08
      • 2014-05-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多