【问题标题】:Rails submit multiple nested forms with one submit buttonRails 使用一个提交按钮提交多个嵌套表单
【发布时间】:2016-04-09 17:05:54
【问题描述】:

我正在为竞赛排行榜构建一个 Rails 应用程序。数据模型是

class Tournament
  has_many :events
end

class User
  has_many :entries
  has_many :events, through: :entries
end

class Events
  has_many :entries
  belongs_to :tournament
end

class Entry
  belongs_to :user
  belongs_to :event
end

每个锦标赛有 2 个赛事,每个赛事用户最多可以输入 4 个条目,因此每个锦标赛总共有 8 个条目。我想允许用户在一个表单中输入所有 8 个条目,并带有一个提交按钮。

我的路线

resources :entries, except: [:index, :show] do
  collection do
    match 'create_collection',  via: [:create]
  end
end

我在 Entries 控制器中还有一个 create_collection 方法来处理条目,尽管我还没有做到这一点。我不确定如何让表单正常工作。

_form.html.haml(由views/tournaments/index.html.haml 部分渲染并传递next_events,这是锦标赛的2 个事件实例。

.entry-form
  = form_tag create_collection_entries_path do |form|
    - next_events.each do |event|
      = event.name
      = fields_for "events[]", event do |f|
        - 4.times do 
          = f.fields_for :entries do |f|
            = f.label_tag 'player'
            = f.text_field 'player'

    = submit_tag "Submit", class: "btn btn-success"

表单按我的预期显示,但是当我单击提交按钮时,只有最后 4 个条目在参数中提交,并且事件 ID 没有被传递

"events"=>[{"entries_attributes"=>
  {"0"=>{"player"=>"player5","id"=>"33"},
   "1"=>{"player"=>"player6", "id"=>"34"},
   "2"=>{"player"=>"player7", "id"=>"35"},
   "3"=>{"player"=>"player8", "id"=>"36"}}}],
"commit"=>"Submit"}

如何获取两个事件的所有入口参数以使用正确的 event-id 提交?

【问题讨论】:

    标签: ruby-on-rails-4 nested-forms nested-attributes form-helpers


    【解决方案1】:

    我的研究表明,Rails 没有提供一种通过一次提交在一个表单中提交模型的多个实例的方法。我查看了thisthis,这对我来说不太适用。所以我推出了自己的。

    以相当易于管理的方式提交参数哈希中的所有值的表单。这不是最优雅的解决方案,需要在后端进行相当多的处理。但我找不到一种更随意的方式来做到这一点。

    form.html.haml

    .entry-form.on
      = form_tag create_collection_entries_path(@user.id) do
        - Tournament.next.events.each do |event|
          %div= event.name
          %div
            - @num_of_entry_forms.times do |n|
              %div
                = label_tag 'player'
                = text_field_tag "event[#{event.id}][entries][player_#{n}]" 
    
        = submit_tag "Submit", class: "btn btn-success"
    

    routes.rb

    resources :entries, except: [:index, :show] do
      collection do
        get '/new_collection/:user_id', to: 'entries#new_collection', as: 'new_collection'
        post '/create_collection/:user_id', to: 'entries#create_collection', as: 'create_collection'
      end
    end
    

    entries_controller.rb

    def new_collection
      @num_of_entry_forms = EventEntryCollectionCreator::MAX_ENTRIES_PER_EVENT
      @user = User.find(params[:user_id])
    end
    
    def create_collection
      @eec = EventEntryCollection.new(params)
      if @eec.save
        redirect_to root_path
      else
        render :new_collection
      end
    end
    

    我仍在开发作为服务模型的 EventEntryCollectionCreator,但这是它的核心。

    MAX_ENTRIES_PER_EVENT = 4
    
    def save
      params["event"].each do |event|
        event.last["entries"]["player"].each do |entry|
          entry = Entry.new(event_id: event.first, user_id: user_id, player: entry.last)
          @entries_collection << entry
        end
      end
      save_collection
    end
    
    private
    def save_collection
      @entries_collection.each do |entry|
        if valid_entry?
          entry.save
          @valid_models << entry
        else
          @invalid_models << entry
        end
      end
    end
    

    正如我所说,这不是最优雅的解决方案,但它解决了问题。好处是杂乱的后端处理从控制器中抽象出来,变成了它自己的服务模型。不利的方面是有一些代码异味,很多强制值进入散列和对象必须对散列结构了解太多。

    我愿意接受其他解决方案或对这项工作进行改进。

    【讨论】:

      猜你喜欢
      • 2016-04-06
      • 2012-01-23
      • 2017-05-03
      • 2011-03-20
      • 2021-08-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多