嵌套表单:创建与两个对象相关的对象也是相关的

时间:2015-11-09 06:50:06

标签: ruby-on-rails ruby-on-rails-4

更新:我做了一些有用的事情,我将把它作为我自己对这个问题的回答。但它绕过了guide_params功能,所以我觉得它不安全。如果有人有更好的方法,我会很感激。

我有三个对象。父是Guide,我有一个嵌套的表单来创建它。指南belongs_to CityObj和CountryObj。这两个模型有很多指南。

我可以使用accepts_nested_attributes_for来正确初始化Guide-CityObj和Guide-CountryObj关系。

皱纹是CityObj和CountryObj彼此相关。 CityObj属于CountryObj,CountryObj has_many CityObj。我不知道在创建指南时如何初始化CityObj-CountryObj关系。

此外,CountryObj.name是唯一的(只有一个法国),而CityObj.name/CountryObj.id是唯一的(只有一个巴黎,法国,但也有一个巴黎,美国)。但我不想使用验证来阻止在现有城市/国家/地区创建指南。法国巴黎应该能够有很多指南。所以我必须能够处理控制器中的重复项。

Guide.rb

class Guide < ActiveRecord::Base
  belongs_to :city_obj
  belongs_to :country_obj

  accepts_nested_attributes_for :city_obj, :country_obj
end

country_obj.rb

class CountryObj < ActiveRecord::Base
  has_many :guides, dependent: :destroy
  has_many :city_obj, dependent: :destroy
end

city_obj.rb

class CityObj < ActiveRecord::Base
  has_many :guide, dependent: :destroy
  belongs_to :country_obj

  accepts_nested_attributes_for :country_obj   # This is not working
end

我想我必须更新指南控制器中的guide_params以将CountryObj传递给CityObj。我试过这个:

def guide_params
      params.require(:guide).permit(:name, 
                                    :description, 
                                    country_obj_attributes: [:name],
                                    city_obj_attributes: [:name, country_obj_attributes: [:name]],
                                    guide_pics_attributes: [:picture]) 
end

我的创建函数调用

@guide = current_user.build_guide(guide_params)

这给了

@guide.city_obj = <a city object>
@guide.country_obj = <a country object>
@guide.country_obj.city_obj = nil

如何设定最终关系?

1 个答案:

答案 0 :(得分:0)

我认为这不安全,因为它绕过了我的guide_params方法,该方法限制了所需的参数。

为了完成这项工作,我在控制器中手动设置了coutnry_obj和city_obj。

def create
  @guide = current_user.build_guide(guide_params)

  set_city_country

  if @guide.save
     ...

end

我使用set_city_country函数进行创建和更新:

def set_city_country
  # Building guide with guide_params is not setting city_obj.country_obj.
  # Also need to manaually ensure city_obj/country_obj and country_obj are unique

  country = params[:guide][:country_obj_attributes][:name]
  city = params[:guide][:city_obj_attributes][:name]

  @guide.country_obj = CountryObj.find_or_create_by(name: country)
  @guide.city_obj = CityObj.find_or_create_by(name: city, 
                                        country_obj_id: @guide.country_obj.id)
  @guide.city_obj.country_obj = @guide.country_obj
end