Почему Rack (Rails) преобразует эти данные сообщения формы в два отдельных объекта Hash?

У меня сейчас есть кобыла, пытающаяся создать сложную HTML-форму с использованием Rails. Так как форма более сложная, чем обычно, я не использую form_for для сложных входных данных.

Вот часть, с которой у меня проблемы:

- users.each do |user|

    .checkbox
      = hidden_field_tag "booking[events][][id]", event.id
      = hidden_field_tag "booking[events][][delegates][][id]", user.id

      = label_tag "booking[events][][delegates][][attending]", for: id_for_event_bookings_checkbox(user, event) do

        = check_box_tag "booking[events][][delegates][][attending]", 1, value_for_event_booking_checkbox(f.object, user, event), id: id_for_event_bookings_checkbox(user, event)
        = user.name

К вашему сведению:

id_for_event_bookings_checkbox # => "booking_form__checkbox_#{user.id}_#{event.id}"

value_for_event_booking_checkbox # => правда/ложь

Когда я публикую эту форму, параметры имеют неверный формат.

Что я получаю:

{"booking"=> {"booker_id"=>"36", "events"=>[{"id"=>"2", "delegates"=>[{"id"=>"35", "attending"=>"1"}]}, {"id"=>"2", "delegates"=>[{"id"=>"36"}]}]}}

Что мне нужно:

{"booking"=> {"booker_id"=>"36", "events"=>[{"id"=>"2", "delegates"=>[{"id"=>"35", "attending"=>"1"}, {"id"=>"36"}]}]}}

Я предполагаю, что мне нужно изменить структуру the check_box_tags name, но я понятия не имею, как их структурировать.

ПРИМЕЧАНИЕ. Я застрял на использовании этой более подробной структуры, потому что StrongParams в Rails отстой.


person bodacious    schedule 26.08.2015    source источник


Ответы (1)


В этом случае попробуйте использовать accepts_nested_attributes_for и fields_for вместо борьбы с Rails.

class Booking < ActiveRecord::Base
  accepts_nested_attributes_for :events
end

class Event
  accepts_nested_attributes_for :delegates
end

Использование form_for и fields_for для генерации ваших полей на самом деле довольно просто:

= form_for(@booking) do |f|
  = f.hidden_field :booker_id
  = f.fields_for :events do |ef|
    = ef.fields_for :delegates do |df|
      = df.label :attending do 
        = df.check_box :attending
      # assumes the delegate is a user
      = df.object.name 

Обратите внимание, что это не даст вам точных желаемых параметров, а вместо этого даст вам параметры, которые работают с соглашениями accepts_nested_attributes_for.

{
  booking: {
    events_attributes: {
      0 => {
        id: 6
        delegates_attributes: {
          0 => {
            id: 6
            attending: 1
          }
        }
      }
    }
  }
}

Вы можете добавить параметры в белый список:

ea = [:id, { delegates_attributes: [:id, :attending] } ]
params.require(:booking)
  .permit(:booker_id, events_attibutes: ea)
person max    schedule 26.08.2015
comment
Если делегат — это какая-то модель соединения между пользователями и событиями, вы можете использовать метод ActiveSupport [delegate] (apidock. com/rails/Module/delegate) или просто df.object.user.name - person max; 26.08.2015
comment
Принимать вложенные атрибуты для не было жизнеспособным решением этой проблемы — форма была слишком сложной. Но спасибо :) - person bodacious; 10.03.2017
comment
Я бы сказал, что основной причиной, вероятно, является плохая архитектура. Вы пытаетесь сделать слишком много за одно действие. Или вы делаете это не на том уровне. - person max; 11.03.2017