Ruby on rails 在一个事务中分配或创建关联模型
我有Ruby on rails 在一个事务中分配或创建关联模型,ruby-on-rails,ruby-on-rails-3,activerecord,Ruby On Rails,Ruby On Rails 3,Activerecord,我有文章,每篇文章都有许多类别 当用户创建或更新文章时,他或她可以填写类别名称,如果此类类别尚不存在,则需要创建一个新类别 型号 class Article < ActiveRecord::Base attr_accessible :category_id, :content, :title, :category_name belongs_to :category def category_name category.try(:name) end def
文章
,每篇文章都有许多类别
当用户创建或更新文章时,他或她可以填写类别名称,如果此类类别尚不存在,则需要创建一个新类别
型号
class Article < ActiveRecord::Base
attr_accessible :category_id, :content, :title, :category_name
belongs_to :category
def category_name
category.try(:name)
end
def category_name=(name)
self.category = Category.find_or_create_by_name(name) if name.present?
end
end
class Category < ActiveRecord::Base
attr_accessible :name
has_many :articles
end
我想得到一些建议/解决方案,如何优雅地解决这个问题
我可能会在我的控制器里写东西
ActiveRecord::Base.transaction do
@article = Article.create(params[:article])
respond_with(@article)
end
但这意味着我必须用两种方法编写相同的代码:create
和update
。因为这违反了干燥原则,我宁愿另找一种方法
def update
article = Article.find(params[:id])
article.attributes = params[:article]
respond_with persist(article)
end
def create
article = Article.new(params[:article])
respond_with persist(article)
end
private
def persist(article)
ActiveRecord::Base.transaction do
return article.save
end
end
老问题,但万一有人正在寻找类似问题的解决方案: 我认为您应该能够在不干扰事务的情况下处理它,并使用嵌套属性,如下所示:
class Article < ActiveRecord::Base
# ...
belongs_to :category
accepts_nested_attributes_for :category
def category_name=(name)
category = Category.find_by(name: name)
if category
self.category_id = category.id
else
self.category_attributes = {name: name}
end
end
end
类文章
因此,如果存在具有该名称的类别,它将只分配类别id。否则,它将通过嵌套属性分配一个新类别,该属性将确保在没有其他验证错误的情况下保持该类别,而在有其他验证错误的情况下不保持该类别。查看Railscast on。这需要一些额外的步骤,但Ryan在解释过程中做得很好。
def update
article = Article.find(params[:id])
article.attributes = params[:article]
respond_with persist(article)
end
def create
article = Article.new(params[:article])
respond_with persist(article)
end
private
def persist(article)
ActiveRecord::Base.transaction do
return article.save
end
end
class Article < ActiveRecord::Base
# ...
belongs_to :category
accepts_nested_attributes_for :category
def category_name=(name)
category = Category.find_by(name: name)
if category
self.category_id = category.id
else
self.category_attributes = {name: name}
end
end
end