如何使用嵌套形式的值设置外键?
How to set foreign key using value from nested form?
我有一个显示 Content
的 Rails 应用程序。每个内容 belong_to 一个 Source
和一个源 has_many 内容。每个 Source 由一个 name
和一个 domain
.
组成
内容还 belongs_to 和 Edition
。我的应用程序的设置方式是,在 create/edit Editions
的表单中,我使用 Cocoon gem.
嵌套了 Contents
的表单字段]
内容的嵌套字段包括一个 link
字段。我需要做的是检查 link
与来源 table 中的各种 domains
并在新的 created/edited 内容上设置相关的 source_id
。
我在想我可以在update
或create
动作的editions controller
中设置相关的source_id
。但是,由于我收到的唯一数据是带有嵌入式 contents_attributes
散列的参数散列(它没有引用 source_id
,因为 source
未在表单中设置),如何我可以使用在表单上提交的 'link' 设置 source_id
吗?
这是我在 editions_controller 上的创建和更新操作:
def create
@edition = Edition.new(edition_params)
respond_to do |format|
if @edition.save
format.html { redirect_to @edition, notice: 'Edition was successfully created.' }
format.json { render :show, status: :created, location: @edition }
else
format.html { render :new }
format.json { render json: @edition.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if @edition.update(edition_params)
format.html { redirect_to @edition, notice: 'Edition was successfully updated.' }
format.json { render :show, status: :ok, location: @edition }
else
format.html { render :edit }
format.json { render json: @edition.errors, status: :unprocessable_entity }
end
end
end
这里是使用的参数:
def edition_params
params.require(:edition).permit(:date,
:clicks,
:product_id,
contents_attributes: [:id,
:heading,
:body,
:link,
:top_story,
:section_id,
:_destroy
]
)
end
我应该在带有 source_id 的表单上隐藏输入吗?或者这可以像在控制器上那样完成吗?
如果您在内容表单中设置了 link
值并且您有根据 link
的值确定 source
的逻辑,那么您不需要设置source_id
在表单中或在控制器中。
设置 source_id
的最佳位置是在模型中,因此无论您如何创建 content
记录,即从版本表单、控制台或某些其他控制器。在这种情况下,您不必担心。
在您的模型中拥有这些关联和回调应该可以解决您的目的:
class Source
# field :name
# field :domain
has_many :contents
def self.fetch_from_link(link)
match_link_with_domains_and_return_source_record
end
end
class Edition
# field :date
# field :clicks
has_many :contents
accepts_nested_attributes_for :contents
end
class Content
# field :heading
# field :body
# field :link
# field :top_story
belongs_to :source
belongs_to :edition
before_validation :set_source
private
def set_source
# Set source *only* if not already set. You can change `||=` to `=` to set it always.
self.source ||= link && Source.fetch_from_link(link)
end
end
我有一个显示 Content
的 Rails 应用程序。每个内容 belong_to 一个 Source
和一个源 has_many 内容。每个 Source 由一个 name
和一个 domain
.
内容还 belongs_to 和 Edition
。我的应用程序的设置方式是,在 create/edit Editions
的表单中,我使用 Cocoon gem.
Contents
的表单字段]
内容的嵌套字段包括一个 link
字段。我需要做的是检查 link
与来源 table 中的各种 domains
并在新的 created/edited 内容上设置相关的 source_id
。
我在想我可以在update
或create
动作的editions controller
中设置相关的source_id
。但是,由于我收到的唯一数据是带有嵌入式 contents_attributes
散列的参数散列(它没有引用 source_id
,因为 source
未在表单中设置),如何我可以使用在表单上提交的 'link' 设置 source_id
吗?
这是我在 editions_controller 上的创建和更新操作:
def create
@edition = Edition.new(edition_params)
respond_to do |format|
if @edition.save
format.html { redirect_to @edition, notice: 'Edition was successfully created.' }
format.json { render :show, status: :created, location: @edition }
else
format.html { render :new }
format.json { render json: @edition.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if @edition.update(edition_params)
format.html { redirect_to @edition, notice: 'Edition was successfully updated.' }
format.json { render :show, status: :ok, location: @edition }
else
format.html { render :edit }
format.json { render json: @edition.errors, status: :unprocessable_entity }
end
end
end
这里是使用的参数:
def edition_params
params.require(:edition).permit(:date,
:clicks,
:product_id,
contents_attributes: [:id,
:heading,
:body,
:link,
:top_story,
:section_id,
:_destroy
]
)
end
我应该在带有 source_id 的表单上隐藏输入吗?或者这可以像在控制器上那样完成吗?
如果您在内容表单中设置了 link
值并且您有根据 link
的值确定 source
的逻辑,那么您不需要设置source_id
在表单中或在控制器中。
设置 source_id
的最佳位置是在模型中,因此无论您如何创建 content
记录,即从版本表单、控制台或某些其他控制器。在这种情况下,您不必担心。
在您的模型中拥有这些关联和回调应该可以解决您的目的:
class Source
# field :name
# field :domain
has_many :contents
def self.fetch_from_link(link)
match_link_with_domains_and_return_source_record
end
end
class Edition
# field :date
# field :clicks
has_many :contents
accepts_nested_attributes_for :contents
end
class Content
# field :heading
# field :body
# field :link
# field :top_story
belongs_to :source
belongs_to :edition
before_validation :set_source
private
def set_source
# Set source *only* if not already set. You can change `||=` to `=` to set it always.
self.source ||= link && Source.fetch_from_link(link)
end
end