如何在 rails 中呈现基于同一模型构建的不同表单

How to render different forms built on the same model in rails

我正在构建一个应用程序,用户可以在其中注册、浏览资助,然后申请他们有资格获得的资助。到目前为止,我对每个模型都有模型:用户、拨款和应用程序。总而言之,用户点击资助页面上的申请按钮,他们将被发送到一个独特的表格,该表格特定于他们作为申请填写的资助。我正在努力解决的部分是每笔赠款都有一个独特的申请表。

到目前为止,我的想法是在应用程序模型中包含所有可能的字段,然后根据授权 ID 调用多个部分(仅包含该授权所需的字段)。我尝试将 submissions/new 上的渲染更改为:

<%= render :partial => "submissions/#{@grant}" %> 

打算根据之前访问过的授权页面的 grant_id 呈现部分内容。

_submission/1.html.erb
_submission/2.html.erb
_submission/3.html.erb  

这不能正常工作,但我不确定我错过了什么。

另一个想法是添加一个单独的提交模型,该模型将 link 拨款和申请通过联合 table 但我仍然有为每个拨款调用唯一表单的问题。

有没有人有解决渲染问题的方法或关于创建许多独特应用程序而无需为每个应用程序构建新模型的替代方法的建议?

我最近不得不实现类似的东西。我在网站的多个位置呈现相同的表单,但通过隐藏字段标记为它们分配了唯一的 content_type。根据附加到表单的内容类型,将向他们发送适当的电子邮件。我会列出我使用的过程,我认为它可以很容易地修改以满足您的需要。

首先我创建了一个名为 contacts 的迁移。对你来说,我想这将是应用程序?

rails g migration contacts

然后我添加了以下字段,

class CreateContacts < ActiveRecord::Migration
  def change
    create_table :contacts do |t|
      t.string :name
      t.string :phone
      t.string :email
      t.text :comment
      t.string :content_type


      t.timestamps
    end
  end
end

添加您认为对您的应用程序必要的任何字段。不过保持 content_type。

rake db:migrate

然后我生成了一个联系人控制器

rails g controller Contacts

,填写如下。非常标准,但请注意 content_type 是我们允许的参数之一。

class ContactsController < ApplicationController

    def new
        @contact = Contact.new
    end

    def create
        @contact = Contact.new(contact_params)

        if @contact.save
            flash[:success] = "Message Sent!"
            redirect_to root_path
        else
            flash[:danger] = "Error occurred"
            render :new
        end
    end

    private
        def contact_params
            params.require(:contact).permit(:name, :phone, :email, :comment, :contact_type)
        end
end

现在我们的表格。在已经生成的views/contacts文件夹下,新建一个文件夹,命名为partials。在此文件夹中创建一个 file 并将其命名为 _form.html.erb 。下划线很重要,因为它是部分的。对不起,如果我过度解释了一些事情。

_form.html.erb

<%= form_tag contacts_path do %>
   <%= hidden_field_tag 'contact[contact_type]', contact_type %>

   <%= text_field_tag 'contact[name]', nil, required: true, placeholder: "Name" %>

   <%= text_field_tag 'contact[phone]', nil, placeholder: "Phone" %>

   <%= email_field_tag 'contact[email]', nil, required: true, placeholder: "Email" %>

   <%= text_area_tag 'contact[comment]', nil, required: true, placeholder: "Comments" %>

   <%= submit_tag "Submit" %>
<% end %>

然后在我看来,无论在您的情况下我想要一个表单或应用程序,我都会呈现部分表单并添加联系人类型。您可以将其保留为 contact_type 或将其命名为 application_type 或您在首次生成上述迁移时想要的任何名称。

<%= render partial: '/contacts/partials/form', locals: {contact_type: 'become_partner'} %>

在我的联系人模型 contact.rb 中,我会在我必须拥有的字段上添加一些验证,并编写一个方法来调用我的 ContactMailer(我还没有创建)。

class Contact < ActiveRecord::Base
    validates :name, presence: true
    validates :email, presence: true

    after_create :send_email

    private
        def send_email
            if self.contact_type == 'become_partner'
                ContactMailer.partner_email(self).deliver
            else
                ContactMailer.contact_email(self).deliver
            end
        end
end

我们的 send_email 方法用于查询附加到表单的 content_type 的类型。你可能有

if self.contact_type == 'application_1(for example)'
      ContactMailer.application_1(self).deliver
elsif self.contact_type == 'application_2'
      ContactMailer.application_2(self).deliver
else
      ContactMailer.application_3(self).deliver
end

根据需要添加任意数量的 elsif

现在让我们创建我们的联系人邮件程序。在文件夹 app/mailers 中创建文件 contact_mailer.rb

class ContactMailer < ActionMailer::Base
    default to: 'justin@socialplayground.com.au'

    def contact_email(contact)
        @contact = contact

        mail(from: @contact.email, subject: 'Contact Form Message').deliver
    end

    def partner_email(contact)
        @contact = contact

        mail(from: @contact.email, subject: 'Contact Form Message').deliver
    end

end

在这里,我们为不同的表单创建所有操作,以发送各自的电子邮件。在上面的示例中,我将 contact_email 作为我的主要主页表单,partner_email 作为合作伙伴注册部分中的表单等。您可能有 application_1、application_2 等,并且感觉随意将主题更改为您想要的任何内容。这是在您打开电子邮件收件箱之前显示在您的电子邮件收件箱中的内容。发件人的姓名和简短消息,例如 "new application for ... " 在您的情况下。

最后..

我们发送的 html 电子邮件。 在视图下创建一个名为 contact_mailer 的文件夹,并在该文件夹中创建具有关联名称的电子邮件。所以对我来说,我的主要主页表单有电子邮件 contact_email.html.erb,我的合作伙伴表单是我创建的 partner_email.html.erb

<!DOCTYPE Html>
<html>
    <head>
        <title></title>
    </head>
    <body>

        <p>New message from RuNpiXelruN's Contact Form!, from <%= "#{@contact.name}, #{@contact.email}" %></p>
        </br>
        <p><%= @contact.name %></p>
        <p><%= @contact.phone %></p>
        <p><%= @contact.comment %></p>

    </body>
</html>

这就是您打开电子邮件时会看到的内容。随意更改消息。

现在一切都应该顺利进行,整个网站只使用一种形式和模型!

此外,我想提一下,如果您有一些特定于某些应用程序的字段,请在您进行初始迁移时创建它们,并在 main _form 部分中查询 content_type。即如果 content_type 是 ..this.. text_field_tag'contact[...example..]'

例如。

还有一件事,现在我们使用一种形式和一种创建方法,如果出现错误,render :new 在我们的控制器中变得有点困难。这就是为什么您可能已经注意到我已将 required: true 添加到我需要的表单的输入中,以处理此处的错误。这样,除非填写正确,否则将不允许提交表单。

测试并确保所有齿轮都正确转动。观察你的服务器日志,因为它正在发生。我将我的应用程序部署到 Heroku。要让它真正通过电子邮件发送,您还需要一个配置步骤。我用 sendgrid 处理了它。如果您不知道如何操作,并且可以按照自己的意愿进行所有操作,请联系我,我会告诉您。祝你好运!

贾斯汀