Rails 3, вложенные многоуровневые формы и has_many через

Я пытаюсь заставить его работать, но это не так!

у меня есть

class User < ActiveRecord::Base
  has_many :events, :through => :event_users
  has_many :event_users
  accepts_nested_attributes_for :event_users
end

class Event < ActiveRecord::Base
  has_many :event_users
  has_many :users, :through => :event_users
  accepts_nested_attributes_for :users
end

class EventUser < ActiveRecord::Base
  set_table_name :events_users
  belongs_to :event
  belongs_to :user
  accepts_nested_attributes_for :events
  accepts_nested_attributes_for :users
end

А также таблица-макет

event_users
  user_id
  event_id
  user_type
events
  id
  name
users
  id
  name

И это моя форма

<%= semantic_form_for @event do |f| %>
  <%= f.semantic_fields_for :users, f.object.users do |f1| %>
    <%= f1.text_field :name, "Name" %>
    <%= f1.semantic_fields_for :event_users do |f2| %>
      <%= f2.hidden_field :user_type, :value => 'participating' %>
    <% end %>
  <% end %>
<%= link_to_add_association 'add task', f, :users %>
<% end %>

Проблема в том, что если я таким образом создам нового пользователя, он не установит значение user_type (но создаст пользователя и event_users с user_id и event_id). Если я вернусь к форме редактирования после создания пользователя и отправлю, то значение user_type будет установлено в events_users. (Я также пробовал без formtastic) Любые предложения? Спасибо!

----редактировать----

Я также пытался иметь event_users перед пользователями

<%= semantic_form_for @event do |f| %>
  <%= f.semantic_fields_for :event_users do |f1| %>
    <%= f1.hidden_field :user_type, :value => 'participating' %>
    <%= f1.semantic_fields_for :users do |f2| %>
      <%= f2.text_field :name, "Name" %>
    <% end %>
  <% end %>
<%= link_to_add_association 'add task', f, :event_users %>
<% end %>

но тогда это только выдает мне ошибку:

Ожидаемый пользователь (# 2366531740), получил ActiveSupport:: HashWithIn DifferentAccess (# 2164210940)

--редактировать--

link_to_association - это метод formtastic-cocoon (https://github.com/nathanvda/formtastic-cocoon), но я пытался использовать другие подходы, но с тем же результатом.

---редактировать----

def create
  @event = Event.new(params[:event])
  respond_to do |format|
    if @event.save
      format.html { redirect_to(@event, :notice => 'Event was successfully created.') }
      format.xml  { render :xml => @event, :status => :created, :location => @event }
    else
      format.html { render :action => "new" }
      format.xml  { render :xml => @event.errors, :status => :unprocessable_entity }                 
    end
  end
end

person jonepatr    schedule 12.01.2011    source источник
comment
Можете ли вы показать нам действие создания контроллера?   -  person Nerian    schedule 14.01.2011


Ответы (2)


Честно говоря, я никогда не пытался редактировать или создавать has_many :through таким образом.

Это заняло некоторое время, и пришлось исправить js внутри formtastic_cocoon, чтобы заставить его работать, так что вот рабочий раствор.

Нужно указать модель EventUser, а потом залить модель User (наоборот никогда не получится).

Итак, внутри моделей вы пишете:

class Event < ActiveRecord::Base
  has_many :event_users
  has_many :users, :through => :event_users
  accepts_nested_attributes_for :users, :reject_if => proc {|attributes| attributes[:name].blank? }, :allow_destroy => true
  accepts_nested_attributes_for :event_users, :reject_if => proc {|attributes| attributes[:user_attributes][:name].blank? }, :allow_destroy => true
end

class EventUser < ActiveRecord::Base
  belongs_to :user
  belongs_to :event
  accepts_nested_attributes_for :user
end

class User < ActiveRecord::Base
  has_many :events, :through => :event_users
  has_many :event_users
end

Потом взгляды. Начните с events/_form.html.haml

= semantic_form_for @event do |f|
  - f.inputs do
    = f.input :name

    %h3 Users (with user-type)
    #users_with_usertype
      = f.semantic_fields_for :event_users do |event_user|
        = render 'event_user_fields', :f => event_user
      .links
        = link_to_add_association 'add user with usertype', f, :event_users

    .actions
      = f.submit 'Save'

(я пока игнорирую ошибки) Затем вам нужно будет указать partial _event_user_fields.html.haml partial (здесь немного волшебства):

.nested-fields
  = f.inputs do
    = f.input :user_type, :as => :hidden, :value => 'participating'
    - if f.object.new_record?
      - f.object.build_user
    = f.fields_for(:user, f.object.user, :child_index => "new_user") do |builder|
      = render("user_fields", :f => builder, :dynamic => true)

и закончить партиал _user_fields (который на самом деле не обязательно должен быть партиалом)

.nested-fields
  = f.inputs do
    = f.input :name

Это должно работать. Обратите внимание, что мне пришлось обновить гем formtastic_cocoon, поэтому вам нужно будет обновить его до версии 0.0.2.

Теперь было бы легко выбрать user_type из простого раскрывающегося списка вместо скрытого поля, например. использовать

= f.input :user_type, :as => :select, :collection => ["Participator", "Organizer", "Sponsor"]

Некоторые мысли (теперь я доказал, что это работает):

  • это всегда будет создавать новых пользователей на лету, фактически устраняя необходимость в EventUser. Разрешите ли вы также выбирать существующих пользователей из раскрывающегося списка?
  • лично я бы изменил это: пусть пользователи назначают себя на событие!
person nathanvda    schedule 19.01.2011
comment
Вау! Я не могу поверить, что вы действительно решили это! Ты мой герой! Большое спасибо!! Причина, по которой организатор добавляет всех участников, заключается в том, что событие добавляется после фактического события, чтобы решить проблемы, связанные с экономикой, которые произошли во время события. Да, я добавляю существующих пользователей! Еще раз спасибо!! - person jonepatr; 20.01.2011
comment
У вас есть идеи, как добавить user_type к пользователю (существующему), выбранному из раскрывающегося списка? - person jonepatr; 20.01.2011
comment
В частичном _event_user_fields теперь я автоматически создаю нового пользователя. Вместо этого вы можете использовать две ссылки: 1 для добавления нового пользователя и 1 для добавления существующего пользователя из раскрывающегося списка. Это достаточно ясно? - person nathanvda; 20.01.2011
comment
Вы бы не хотели взглянуть на мою очень похожую проблему, не так ли? stackoverflow.com/ вопросы/11199572/ - person ctilley79; 26.06.2012

В модели events_users нет столбца ID? Поскольку есть дополнительное поле (user_type), EventUser является моделью и, вероятно, должен иметь идентификатор. Возможно, именно поэтому user_type не устанавливается в вашем первом случае.

person Costa Walcott    schedule 14.01.2011
comment
Я пытался добавить идентификатор, но это не имеет никакого значения: / - person jonepatr; 14.01.2011
comment
Странно то, что он ставится при обновлении, а не при создании! - person jonepatr; 14.01.2011