在 has_many 中创建重复记录:通过关联

发布于 2024-10-18 06:21:15 字数 2751 浏览 4 评论 0原文

我有三个模型:Booking、ExtraNight 和 BookedExtraNight。 Running Rails 2.3.11

Booking:

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

现在,由于应用程序的工作方式,在创建 booking_extra_night 时预订就存在。 Booking_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。

现在一切正常,直到创建了 Booking_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 个 Booking_extra_nights 并按提交,我最终会得到 8 条记录。

我还发现,如果我在创建预订的同时创建一个 booking_extra_night 记录,那么我可以添加任意数量的记录,而无需重复。 据我所知,这种情况发生在所有 2.3.x 版本的 Rails 上,所以这显然是我做错了。任何帮助将不胜感激,因为它正在我的头脑中。

谢谢!

I have three models: Booking, ExtraNight and BookedExtraNight. Running Rails 2.3.11

Booking:

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

Now because of the way the application works the booking exists when the booked_extra_night is created. A booked_extra_night is created with the Booking Update action.
In the view the booked_extra_night is built using:

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

I use nested_form_for @booking and f.fields_for :booked_extra_nights to create the booked_extra_nights.

Now everything works fine until I press submit (update action) when two copies of the booked_extra_night is create.

See log:

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

As you can see two identical records is created, now if I were to build 4 booked_extra_nights and press submit I'd end up with 8 records.

I've also found out that if I create a booked_extra_night record at the same time the booking is created then I can add as many as I want doing the above without duplicates.
This happens on all 2.3.x versions of rails as far as I know, so it's obviously something I'm doing wrong. Any help would be greatly appreciated since it's doing my head in.

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

稚然 2024-10-25 06:21:15

我也遇到过这个问题,我的解决方案是在我的控制器中,不使用构建,而是使用 new 并提供父参数。

在我的代码中提取.. 而不是使用

@new_brand = @company.brands.build/new

我使用

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

第一个将此对象作为空对象添加到@company,然后当您提交它时在您的内部创建另一个新对象创造行动。

第二个只是为了表单的目的在内存中创建一个新对象,但是当将值提交给创建操作时,没有与公司绑定的对象

I've had this problem as well, and my solution was in my controller, to not use the build, and to use new and supply the parent parameter.

Extract in my code.. Instead of using

@new_brand = @company.brands.build/new

I use

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

The first adds this object to the @company as an empty object, then when you submit its create another new one within your create action.

The second just creates a new object in memory for the purposes of the form, but when the values are submitted to the create action, there are no objects tied to the company

方觉久 2024-10-25 06:21:15

谢谢,兔子!遗憾的是,你让我走上了正轨,但更新操作一团糟。
我已经重新考虑了它,现在一切正常了,我认为双重保存与我首先更新预订,然后重定向,然后通过 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

功能相同,但少了很多行。而且它不会造成重复的额外住宿。

谢谢,兔子。你的回答让我思考,因为我曾多次尝试更改视图和模型中的内容但没有成功。我只是假设控制器可以工作,因为它可以用于其他所有事情。

Thanks, Rabbot! You got me on the right track, sad to say, but the update action were a mess.
I've re-factored it and now everything works, I think the double saves had to do with me first updating the booking, then redirecting, then updating the booking again through AASM.

Below is the old update action (I told you it was a mess):

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

And this is the new, re-factored update action.

  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

Same functionality, many many lines less. And it does not create duplicate extra nights.

Thanks, Rabbot. Your answer made me think, as I'd tried changing stuff in the view and model several times without success. I just assumed the controller worked since it worked for everything else.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文