Повторяющиеся записи, созданные в has_many: через ассоциации - PullRequest
2 голосов
/ 21 февраля 2011

У меня есть три модели: Booking, ExtraNight и BookedExtraNight. Ходовые рельсы 2.3.11

Бронирование:

has_many :extra_nights, :through => :booked_extra_nights
has_many :booked_extra_nights, :dependent => :destroy

ExtraNight:

has_many :booked_extra_nights, :dependent => :destroy
has_many :bookings, :through => :booked_extra_nights

BookedExtraNight:

belongs_to  :extra_night
belongs_to  :booking

Теперь из-за того, как приложение работает, резервирование существует при создании booked_extra_night. Booked_extra_night создается с действием обновления бронирования. В представлении booked_extra_night построен с использованием:

<% unless @booking.booked_extra_nights.exists? %>
   <% @booking.booked_extra_nights.build %>
<% end %>

Я использую nested_form_for @booking и f.fields_for: booked_extra_nights для создания booked_extra_nights.

Теперь все работает нормально, пока я не нажму submit (обновление), когда создаются две копии booked_extra_night.

см. Журнал:

Processing BookingsController#update (for 127.0.0.1 at 2011-02-21 07:44:22) [PUT]
Parameters: {"action"=>"update", "_method"=>"put",   "authenticity_token"=>"b/M+VjMxA8RFqbubhBeF494B/zhxi/2Eb3EtoCoRLx0=",  "id"=>"5b2jwg7qw5na3vz4nt", "booking"=>{"booked_extra_nights_attributes"=>{"0"=> {"number_of_days"=>"2", "from_date(1i)"=>"2011", "from_date(2i)"=>"9", "from_date(3i)"=>"1",  "_destroy"=>"", "extra_night_id"=>"7"}}}, "controller"=>"bookings"}
Booking Load (1.3ms)   SELECT * FROM "bookings" WHERE ("bookings"."random_url_key" =  '5b2jwg7qw5na3vz4nt') LIMIT 1
Variant Load (0.6ms)   SELECT * FROM "variants" WHERE ("variants"."id" = 27) 
SQL (0.1ms)   BEGIN
SQL (0.7ms)   INSERT INTO "booked_extra_nights" ("number_of_days", "created_at",   "updated_at", "booking_id", "from_date", "extra_night_id") VALUES(2, '2011-02-21  06:44:22.525154', '2011-02-21 06:44:22.525154', 69, '2011-09-01', 7) RETURNING "id"
SQL (0.8ms)   COMMIT
SQL (0.6ms)   BEGIN
SQL (0.6ms)   INSERT INTO "booked_extra_nights" ("number_of_days", "created_at",  "updated_at", "booking_id", "from_date", "extra_night_id") VALUES(2, '2011-02-21 06:44:22.544452', '2011-02-21 06:44:22.544452', 69, '2011-09-01', 7) RETURNING "id"
SQL (25.8ms)   COMMIT
SQL (0.1ms)   BEGIN
Booking Update (0.6ms)   UPDATE "bookings" SET "updated_at" = '2011-02-21 06:44:22.575409', "aasm_state" = 'step3' WHERE "id" = 69
SQL (0.5ms)   COMMIT
Redirected to http://localhost:3000/bookings/5b2jwg7qw5na3vz4nt/step3

Как видите, созданы две идентичные записи, теперь, если бы я собрал 4 booked_extra_nights и нажал submit, я бы получил 8 записей.

Я также узнал, что если я создаю запись booked_extra_night в то же время, когда создается бронирование, тогда я могу добавить столько, сколько я хочу, без дубликатов. Насколько я знаю, это происходит на всех версиях рельсов 2.3.x, так что, очевидно, я что-то не так делаю. Любая помощь будет принята с благодарностью, так как она делает мою голову.

Спасибо!

Ответы [ 2 ]

0 голосов
/ 22 февраля 2011

Спасибо, Раббот!К сожалению, вы вывели меня на правильный путь, но действия по обновлению были беспорядочными.Я пересмотрел его, и теперь все работает, я думаю, что двойное сохранение было связано со мной, сначала обновив бронирование, затем перенаправив, затем обновив бронирование снова через AASM.

Ниже приведенстарое действие обновления (я говорил вам, что это беспорядок):

def update
  @booking = Booking.find_by_random_url_key(params[:id])
  @variant = @booking.variant
  if params[:back_button]
    if @booking.aasm_state == "step2"
      redirect_to booking_step1_url(@booking)
    elsif @booking.aasm_state == "step3"
      redirect_to booking_step2_url(@booking)
    elsif @booking.aasm_state == "step4"
      redirect_to booking_step3_url(@booking)
    elsif @booking.aasm_state == "step5"
      redirect_to booking_step4_url(@booking)
    end
    @booking.previous!
  else
    if @booking.update_attributes(params[:booking]) && @booking.aasm_state == "step1"
      redirect_to booking_step2_url(@booking)
      @booking.next!
    elsif @booking.update_attributes(params[:booking]) && @booking.aasm_state == "step2"
      @booking.next!
      redirect_to booking_step3_url(@booking)
    elsif @booking.update_attributes(params[:booking]) && @booking.aasm_state == "step3"
      redirect_to booking_step4_url(@booking)
      @booking.next!
    elsif @booking.update_attributes(params[:booking]) && @booking.aasm_state == "step4"
      redirect_to booking_url(@booking)
      @booking.next!
    end
  end
end

И это новое, переработанное действие обновления.

  def update
    @booking = Booking.find_by_random_url_key(params[:id])
    @variant = @booking.variant
    if params[:back_button]
      @booking.previous!
      redirect_to :controller => "bookings", :action => "#{@booking.aasm_state}", :id => @booking
    else
      @booking.update_attributes(params[:booking])
      @booking.next!
      redirect_to :controller => "bookings", :action => "#{@booking.aasm_state}", :id => @booking
    end
  end

Та же функциональность, много много строк меньше.И это не создает дубликатов дополнительных ночей.

Спасибо, Раббот.Ваш ответ заставил меня задуматься, поскольку я несколько раз безуспешно пытался изменить вид и модель.Я просто предположил, что контроллер работает, поскольку он работает для всего остального.

0 голосов
/ 21 февраля 2011

У меня тоже была эта проблема, и мое решение было в моем контроллере, чтобы не использовать сборку, а использовать new и предоставить родительский параметр.

Извлечь в моем коде .. Вместо использования

@new_brand = @company.brands.build/new

Я использую

@new_brand = Brand.new(:company => @company)

Сначала этот объект добавляется в @company как пустой объект, затем, когда вы отправляете его, создаете еще один новый в действии create.

Второй просто создает новый объект в памяти для целей формы, но когда значения передаются в действие создания, объекты не связаны с компанией

...