Rails - 从子窗体创建父实例

Rails - Create parent instance from child form

我正在尝试做某种与 'accepts_nested_attributes' 相反的事情。我想从 'children_controller#create' 创建一个父实例。也许您会有一些建议或向我解释这样做无关紧要。我对每条评论都持开放态度!

我有一个客户端模型:

class Client < ActiveRecord::Base
  has_one :magazine
  validates :name, presence: true, uniqueness: true
end

还有一个杂志模特:

class Magazine < ActiveRecord::Base
  belongs_to :client
  validates :client, :launch_date, presence: true
  # accepts_nested_attributes_for :client
end

我正在使用 react-rails gem 并且在 /magazines 我有一个表单来创建一个新杂志,其中包含一个文本字段来提供客户名称。

在我的 magazines_controller.rb 中,我输入了以下内容

def create
  @client = Client.find_by_name(magazine_params[:client_id])
  @selected_magazine = Magazine.new(magazine_params)
  authorize @selected_magazine
  if @client
    @selected_magazine.client = @client
  else
    @client = Client.new(name: magazine_params[:client_id])
    @client.save
    @selected_magazine.client = @client
  end
  # @client = Client.where(name: magazine_params[:client_id]).first_or_create
  # @selected_magazine.client = @client if @selected_magazine.client_id.to_i == 0
  @title = magazine_params[:title]
  @selected_issue = nil
  @issues = nil
  @selected_magazine.save
  binding.pry
  @magazines = policy_scope(Magazine)
end

def magazine_params
  magazine_params = params.require(:magazine).permit(:title, :analytics_id, :launch_date, :client_id)
  # if @client
  #   params[:magazine][:client_id] = @client.id
  #   magazine_params.merge!(params[:magazine])
  # end
  return magazine_params
end

我总是以 PG::Error:

PG::ForeignKeyViolation - ERROR:  insert or update on table "magazines" violates foreign key constraint "fk_rails_cd907cfe6d"
DETAIL:  Key (client_id)=(51) is not present in table "clients".

好像客户端没有保存在数据库中。当我 binding.pry 并调用 Client.all after @client.save 时,它不会 return 我的新客户。

我有点惊讶,因为在另一个项目中我遇到了类似的问题并且这样做效果很好。供您参考:

# Previous Project
# Gemfile.lock
pg (0.18.3)
rails (4.2.0)

#Current Project
# Gemfile.lock
pg (0.18.4)
rails (4.2.5.1)

在此先感谢您的帮助。如果您对在 children_controller 的子实例之前创建父实例的良好做法有任何建议,我真的很感兴趣。

PS1:在控制器中,我先尝试使用注释或创建,但输出仍然相同。 PS2:如果您需要有关 Gemfile 的更多信息,请告诉我。

请尝试下面的代码,这应该可以解决问题。我认为问题在于你试图在拯救客户之前拯救杂志。此外,您应该检查 @client.valid? 是否为真,如果不是,则检查 @client.errors。另外,重写控制器如下,

def create
  @client = Client.find_by_name(params[:magazine][:client_id])

  if @client.nil?
    @client = Client.new(name: params[:magazine][:client_id])
  end

  @selected_magazine = @client.magazines.new(magazine_params)

  authorize @selected_magazine

  @title = magazine_params[:title]
  @selected_issue = nil
  @issues = nil

  @client.save
  @magazines = policy_scope(Magazine)
end

def magazine_params
  params.require(:magazine).permit(:title, :analytics_id, :launch_date)
end

您可以参考http://www.amooma.de/screencasts/2015-01-22-nested_forms-rails-4.2/。用例子解释得很好。它可能会解决您的问题。

您可能想尝试 inverse_of 您的联想,例如:

class Client < ActiveRecord::Base
  has_one :magazine, inverse_of: :client
  validates :name, presence: true, uniqueness: true
end

class Magazine < ActiveRecord::Base
  belongs_to :client, inverse_of: magazine
  validates :client, :launch_date, presence: true
  # accepts_nested_attributes_for :client
end

进一步阅读:http://guides.rubyonrails.org/association_basics.html#bi-directional-associations

不过,一般用例是 has_many