通过 fields_for 以 Rails 形式创建多个实例以及如何访问结果哈希

Creating multiple instances through fields_for in a Rails form and how to access the resultant hash

我之前问过一个相关问题here。但是,由于我无法得到答案,这可能令人困惑。因此,我将问一个更简单的问题。对于我的邀请模型,我如何一次提交超过 1 个邀请以及提交后我如何访问结果 array/collection 哈希中的数据?

Invitations 模型有一个 :email 字符串属性,通过表单提交,我想实现如下内容(我假设这将是最好的设置?):

"@invitation" => {
  "@invitations" => [
    {"email" => "example@hotmail.com" },
    {"email" => "example@yahoo.com"},
    {"email" => "example@gmail.com"}
  ]
}

以下是我目前的代码:

模特

class Scoreboard < ActiveRecord::Base

has_many :invitations

end

class Invitation < ActiveRecord::Base

  belongs_to :scoreboard     

end

邀请函#new View

<%= form_for [@scoreboard, @invitation] do |f| %> 
        <%= render 'shared/error_messages', object: f.object %>

       <%= f.fields_for :invitations do |invites| %> <!-- Tried Many things here with no success -->
         <div>
         <%= invites.label :email %> 
         <%= invites.text_field :email %> 
         </div>
       <% end %>

        <%= f.submit "Send Invitation", class: "btn btn-primary" %>
    <% end %>

邀请控制器

class InvitationsController < ApplicationController

    def new
        @scoreboard = Scoreboard.find(params[:scoreboard_id])
        @invitation= @scoreboard.invitations.build 
    end

    def create
    @scoreboard = Scoreboard.find(params[:scoreboard_id])
    @invitation = @scoreboard.invitations.build(invitation_params)

    if @invitation.save
      flash[:success] = "Invitation sent successfully"
    else
        render 'new'
    end
    end

private

def invitation_params
    params.require(:invitation).permit(:email)
end

end

邀请#create View

<p> Display all the emails here for all the invitations <p> 

在我的 original question 中,我想访问已保存的电子邮件以便我可以向他们发送邮件,但是如果我能弄清楚如何在此视图上显示所有电子邮件,我就能找到方法array/hash collections 有效并使用该信息将它们邮寄出去。

编辑: 之前已经创建了记分板。我的目标是构建多个可以与@scoreboard 相关联的@invitations 实例。这样做的原因是因为我将邮寄到邀请中的电子邮件地址,并且需要在邮件正文中提供有关@scoreboard 的详细信息。

您首先需要确保您的记分板模型可以accept nested attributes for :invitations

然后您需要声明这些属性是记分板控制器中允许的散列的一部分params.require(:scoreboard).permit(:whatever_scoreboard_attributes_you_have, invitations_attributes: [:email, :etc])

然后在您的邀请控制器新操作中,您需要指定要为每个表单构建多少邀请。假设是 3:

    def new
     @scoreboard = Scoreboard.find(params[:scoreboard_id])
       3.times do @invitation= @scoreboard.invitations.build 
       end
    end

这将允许您为每个记分板创建 3 个邀请。

你也应该看看 this Railscast

再次查看您的代码后,我将添加另一个答案,因为我不确定您是否需要为记分牌嵌套。

在您的邀请新视图中:

<%= form_for [@invitation] do |f| %> 
    <%= render 'shared/error_messages', object: f.object %>
     <div>
     <%= f.label :email %> 
     <%= f.text_field :email %> 
     <%= f.hidden_field :scoreboard_id, :value => @scoreboard_id %>
     </div>

    <%= f.submit "Send Invitation", class: "btn btn-primary" %>
<% end %>

然后在您的邀请控制器中,您只需定义@scoreboard:

def new
    @invitation= Invitation.new(scoreboard_id: [:scoreboard_id])
end

因为您似乎没有在记分牌控制器中执行任何操作。

如果这不适用于隐藏字段(不确定是否可行,具体取决于代码的调用方式),那么您需要找到一种方法将 Scoreboard_id 发送到新操作邀请控制器。您通常可以在 HTTP 请求中发送它,或者它可能已经存储在您应用程序的会话中。