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
我正在尝试做某种与 '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