如何在没有从/show.html.erb页面提交的新模板的情况下创建表单

时间:2015-11-12 01:47:09

标签: ruby-on-rails forms ruby-on-rails-4

我有这个应用程序,我正在尝试使用谱系表添加狗家庭关系(狗A是狗B的兄弟姐妹)。但是我在制作能够实现这一目标的形式时遇到问题。 This is how my form looks like at the moment.

正如您可以看到表单在狗配置文件页面中加载,用户可以选择他的一只狗并创建关系。这是来自views / pedigrees / _form.html.erb的views / dog / show.html.erb页面中呈现的表单代码:

<%= form_for(@pedigree, url: new_pedigree_path, html: {method: :post}) do |d| %>
    Select your dog:
    <%= d.collection_select(:dog_id, @dogs,:id, :dname, :prompt => "Select your dog") %>
    <br>
    Select your dog relation to the dog from this profile:
    <%= select_tag(:relation_name, options_for_select([['Sibling', 1], ['Parent', 2], ['Grandparent', 3],
                                                       ['Great-grandparent', 4], ['Child', 5], ['Grandchild', 6], ['Great-grandchild', 7]])) %>
    <br>
    <%= d.submit 'Add Relation' %>
<% end %>

我在生成的源代码中获得的内容如下:

 <form class="new_pedigree" id="new_pedigree" action="/pedigree/new" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="&#x2713;" /><input type="hidden" name="authenticity_token" value="RYOjO10gUvVUQkRaqyum8wB0VJrTwm8MQ6WxIJ3eM4ukP2zHHDECFaT8UUYytSv2OGBUGhvK4k3fwOt+xDfabA==" />

当我点击按钮提交表单时,我收到以下错误:

Missing template pedigree/new, application/new with...

如何操作form_for以便在不需要新表单模板的情况下呈现谱系关系?如何在按下提交按钮时调用#create方法?感谢。

3 个答案:

答案 0 :(得分:1)

为了避免对"/pedigrees"网址进行硬编码,您的表单部分中的第一行应为

<%= form_for(@pedigree, url: pedigrees_path, html: {method: :post}) do |d| %>

您需要了解newcreate操作(及其关联的路径/路径/网址)之间的区别。 new_pedigree_path不是您想要实际创建新记录时使用的路径。 (new_pedigree_path仅用于获取表单。)相反,实际创建新谱系是通过对pedigrees_path的POST请求完成的。

                   Controller Action   HTTP Verb       Path Helper          Path
Get a form
for making a              new            GET          new_pedigree_path     /new_pedigree
new relationship 

Send data about
the new relationship     create          POST          pedigrees_path       /pedigrees
to the server; create
the new record. 

答案 1 :(得分:1)

因为看起来你是新手,所以让我添加一些背景信息。

您目前正在dogs#show页面上调用该表单。这意味着您必须对url进行硬编码 - 传递@pedigree变量应该为Rails提供将表单提交到pedigrees#create所需的信息:

<%= form_for @pedigree do |d| %>
    Select your dog:
    <%= d.collection_select :dog_id, @dogs,:id, :dname, prompt: "Select your dog" %>

    Select your dog relation to the dog from this profile:
    <%= select_tag(:relation_name, options_for_select [['Sibling', 1], ['Parent', 2], ['Grandparent', 3],
                                                       ['Great-grandparent', 4], ['Child', 5], ['Grandchild', 6], ['Great-grandchild', 7]]) %>
    <%= d.submit 'Add Relation' %>
<% end %>

如果您设置了@pedigree变量,则应将表单发送到pedigrees#createpedigrees#update(具体取决于您是使用Pedigree.new设置变量还是Pedigree.find)。

由于您通过部分调用表单,我高度建议仅使用 local 变量:

#app/controllers/dogs_controller.rb
class DogsController < ApplicationController
   def show
      @dog = Dog.find params[:id]
      @pedigree = ...
   end
end

#app/views/dogs/show.html.erb
<%= render "pedigrees/form", locals: {pedigree: @pedigree} %>

#app/views/pedigrees/_form.html.erb
<%= form_for pedigree ...

这可能看起来效率低下,但是您必须记住,partials可以在您的应用中的任何位置使用。在其中使用@instance_variables实际上是antipattern的一半!

其他一些说明:

<强> 1。切勿使用HTML进行“样式化”

我看到有人使用<br><p>在HTML中创建换行符。

虽然这“有效”,但这不正确。事实上,它是彻头彻尾的破坏性(特别是当您使用更大的应用程序时)。

HTML 视为标记(格式); CSS是样式所需要的:

<%= form_for @pedigree do |d| %>
   <%= d.text_field :name %>
   <%= d.text_field :type %>
<% end %>

这就是HTML的外观,然后您可以使用following CSS to style it

#app/assets/stylesheets/application.css
form input {
   display: block;
   margin: 3px 0;
}

如果出于正当理由需要换行(也许你正在使用列表或其他东西),那么请务必使用<br> - 但绝不要用它来创建边距/填充的错觉。< / p>

除此之外,它将使用响应式界面等方式破坏您的样式。

-

<强> 2。许多对多

我不知道您的Rails级别,如果这对您来说过于简单,请道歉。

如果你使用many-to-many关系,我相信你可以大规模改善这一点,特别是has_many :through

enter image description here

#app/models/dog.rb
class Dog < ActiveRecord::Base
   has_many :pedigrees
   has_many :relations, through: :pedigrees
end

#app/models/pedigree.rb
class Pedigree < ActiveRecord::Base
   belongs_to :dog
   belongs_to :relation
end

#app/models/relation.rb
class Relation < ActiveRecord::Base
   has_many :pedigrees
   has_many :dogs, through: :pedigrees
end

这样您就可以通过一次通话填充@dog.pedigrees@dog.relations。因此,您无需使用create / edit新的“血统”记录,而只需使用dog

#app/controllers/dogs_controller.rb
class DogsController < ApplicationController
   def show
      @dog = Dog.find params[:id]
   end

   def update

   end

   private

   def dog_params
      params.require(:dog).permit(:name, :relation_ids)
   end
end

这将允许您使用以下内容:

#app/views/dogs/show.html.erb
<%= form_for @dog do |f| %>
   <%= f.text_field :name %>
   <%= f.collection_select :relation_ids, Relation.all, :id, :name %>
   <%= f.submit %>
<% end %>

这应该允许您选择您的狗拥有的各种“关系”,自动创建Pedigree条记录。

答案 2 :(得分:0)

我能够通过以下方式解决这个问题:

我必须硬编码form_for

<%= form_for(@pedigree, url: "/pedigrees", html: {method: :post}) do |d| %>

我的路线文件中也出错了。而不是资源:谱系y有资源:血统。