【问题标题】:How to render different forms built on the same model in rails如何在rails中渲染建立在同一模型上的不同表单
【发布时间】:2016-04-24 07:05:08
【问题描述】:

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

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

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

它打算根据之前访问的授权页面的grant_id来呈现部分。

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

这不起作用,但我不确定我错过了什么。

另一个想法是添加一个单独的提交模型,该模型将通过连接表链接授权和应用程序,但我仍然遇到为每个授权调用唯一表单的问题。

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

【问题讨论】:

  • 不清楚您所说的“这不起作用”是什么意思。它没有做你想让它做的事情怎么办?
  • 我收到错误消息“部分名称 (submission/) 不是有效的 Ruby 标识符”我也不认为部分名称正在获取先前访问的授权页面的授权 ID。跨度>

标签: ruby-on-rails conditional render jointable


【解决方案1】:

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

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

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 等,并且可以随意将主题更改为您想要的任何内容。这是在您打开它之前显示在您的电子邮件收件箱中的内容。发件人的姓名和简短的消息,例如,在您的情况下为“新申请...”。

最后..

我们发送的 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 '联系人[...示例..]'

例如。

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

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

贾斯汀

【讨论】:

  • 感谢这个解决方案,非常全面且易于理解,稍加修改即可满足我的需求。
猜你喜欢
  • 1970-01-01
  • 2019-05-31
  • 2012-06-24
  • 1970-01-01
  • 1970-01-01
  • 2017-08-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多