Rails replace collection instead of adding to it f

2019-06-16 17:28发布

I have these models (simplified for readability):

class Place < ActiveRecord::Base
  has_many :business_hours, dependent: :destroy

  accepts_nested_attributes_for :business_hours
end

class BusinessHour < ActiveRecord::Base
  belongs_to :place
end

And this controller:

class Admin::PlacesController < Admin::BaseController
  def update
    @place = Place.find(params[:id])

    if @place.update_attributes(place_params)
      # Redirect to OK page
    else
      # Show errors
    end
  end

  private

  def place_params
    params.require(:place)
      .permit(
        business_hours_attributes: [:day_of_week, :opening_time, :closing_time]
      )
  end
end

I have a somewhat dynamic form which is rendered through javascript where the user can add new opening hours. When submitting these opening hours I would like to always replace the old ones (if they exist). Currently if I send the values via params (e.g.):

place[business_hours][0][day_of_week]: 1
place[business_hours][0][opening_time]: 10:00 am
place[business_hours][0][closing_time]: 5:00 pm
place[business_hours][1][day_of_week]: 2
place[business_hours][1][opening_time]: 10:00 am
place[business_hours][1][closing_time]: 5:00 pm

... and so forth

These new business hours get added to the existing ones. Is there a way to tell rails to always replace the business hours or do I manually have to empty the collection in the controller every time?

3条回答
别忘想泡老子
2楼-- · 2019-06-16 17:41

You miss id of business_hours try:

def place_params
    params.require(:place)
      .permit(
        business_hours_attributes: [:id, :day_of_week, :opening_time, :closing_time]
      )
end

That's why the form is adding a new record instead of updating it.

查看更多
SAY GOODBYE
3楼-- · 2019-06-16 17:42

This is the best I could get:

def business_hours_attributes=(*attrs)
  self.business_hours = []
  super(*attrs)
end

Hopefully is not too late.

查看更多
【Aperson】
4楼-- · 2019-06-16 17:57

Bit optimizing the solution proposed @robertokl, to reduce the number of database queries:

def business_hours_attributes=(*args)
  self.business_hours.clear
  super(*args)
end
查看更多
登录 后发表回答