为了账号安全,请及时绑定邮箱和手机立即绑定

Rails表单中的多个对象

/ 猿问

Rails表单中的多个对象

慕的地2183247 2019-11-12 09:30:59

我想以一种形式编辑模型照片的多个项目。我不确定如何正确显示和发布此表单,以及如何在控制器的update动作中收集项目。


这就是我要的:


<form>

<input name="photos[1][title]" value="Photo with id 1" />

<input name="photos[2][title]" value="Photo with id 2" />

<input name="photos[3][title]" value="Custom title" />

</form>

参数只是一个例子,就像我上面所说的那样:我不确定以这种形式发布这些值的最佳方法。


在控制器中,我想要这样的事情:


@photos = Photo.find( params[photos] )

@photos.each do |photo|

    photo.update_attributes!(params[:photos][photo] )

end


查看完整描述

3 回答

?
慕仙森

在Rails 4中,就是这样


<%= form_tag photos_update_path do %>

  <% @photos.each do |photo| %> 

    <%= fields_for "photos[]", photo do |pf| %>

      <%= pf.text_field :caption %>

      ... other photo fields


查看完整回答
反对 回复 2019-11-12
?
慕标5265247

更新:此答案适用于Rails 2,或者如果您有需要自定义逻辑的特殊约束。如在别处讨论的那样,使用fields_for很好地解决了简单的情况。

Rails并不会为您提供很多帮助。它违反了标准的视图约定,因此您必须在视图,控制器甚至路由中进行变通。没意思


使用Rails方式处理多模型表单的关键资源是Stephen Chu的params-foo系列,或者如果您使用的是Rails 2.3,请查看嵌套对象表单


如果您定义了某种正在编辑的单一资源(例如照片集),它将变得更加容易。Photoset可以是真实的ActiveRecord模型类型,也可以只是接受数据并引发错误的外观,就像是ActiveRecord模型一样。


现在,您可以编写如下所示的视图表单:


<%= form_for :photoset do |f|%>

  <% f.object.photos.each do |photo| %>

    <%= f.fields_for photo do |photo_form| %>

      <%= photo_form.text_field :caption %>

      <%= photo_form.label :caption %>

      <%= photo_form.file_field :attached %>

    <% end %>

  <% end %>

<% end %>

您的模型应验证进入的每个子照片并汇总其错误。您可能想查看一篇不错的文章,介绍如何在任何类中包括Validation。它可能看起来像这样:


class Photoset

  include ActiveRecord::Validations

  attr_accessor :photos


  validate :all_photos_okay


  def all_photos_okay

    photos.each do |photo|

      errors.add photo.errors unless photo.valid?

    end

  end


  def save

    photos.all?(&:save)

  end


  def photos=(incoming_data)

    incoming_data.each do |incoming|

       if incoming.respond_to? :attributes

         @photos << incoming unless @photos.include? incoming

       else

         if incoming[:id]

            target = @photos.select { |t| t.id == incoming[:id] }

         end

         if target

            target.attributes = incoming

         else

            @photos << Photo.new incoming 

         end

       end

    end

  end


  def photos

     # your photo-find logic here

    @photos || Photo.find :all

  end

end

通过为Photoset使用外观模型,您可以使控制器和视图逻辑保持简单明了,并为专用模型保留最复杂的代码。该代码可能不会立即可用,但希望它将为您提供一些想法,并为您指出解决问题的正确方向。


查看完整回答
反对 回复 2019-11-12
?
尚方宝剑之说

Rails确实有做到这一点的方法-我不知道它何时被引入,但基本上在这里进行了描述:http : //guides.rubyonrails.org/form_helpers.html#using-form-helpers


在没有父对象的情况下,需要花些时间来适当地更改配置,但这似乎是正确的(它与gamov的答案基本相同,但是更简洁,并且不允许将“新”记录与“更新”记录):


<%= form_tag photos_update_path do %>

  <% @photos.each do |photo| %> 

    <%= fields_for "photos[#{photo.id}]", photo do |pf| %>

      <%= pf.text_field :caption %>

        ... [other fields]

    <% end %>

  <% end %>

<% end %>

在您的控制器中,您将在中得到一个哈希params[:photos],其中的键是照片ID,值是属性哈希。


查看完整回答
反对 回复 2019-11-12
  • 3 回答
  • 0 关注
  • 46 浏览
我要回答

相关问题推荐

添加回答

回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信