У меня есть articles
и каждая статья has_many categories
.Присвоить или создать ассоциированную модель за одну транзакцию
Когда пользователь создает или обновляет статью, он может заполнить название категории и, если такая категория еще не существует, необходимо создать новую.
Модели
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
Контроллер
class ArticlesController < ApplicationController
load_and_authorize_resource
respond_to :json
def create
@article = Article.create(params[:article])
respond_with(@article)
end
def update
@article.update_attributes(params[:article])
@article.save
respond_with(@article)
end
...
end
Проблема
На create
или update
действий, если категория еще не существует, пе w будет создан в отдельной транзакции. Так что, если в произошла ошибка, в любом случае можно создать новую категорию.
Журнал создания действия/обновления (обрезается для краткости):
(0.0ms) begin transaction
SQL (0.3ms) INSERT INTO "categories" ....
(35.1ms) commit transaction
(0.0ms) begin transaction
SQL (0.5ms) INSERT INTO "articles" ...
(32.2ms) commit transaction
Я хотел бы получить некоторые советы/решение, как решить эту проблему в элегантный способ.
я мог бы написать в мой контроллер
ActiveRecord::Base.transaction do
@article = Article.create(params[:article])
respond_with(@article)
end
, но это означает, что я должен написать один и тот же код в обоих методах: create
и update
. Поскольку он нарушает принцип DRY, я бы предпочел найти другой способ.
Взгляните на Railscast на [Токен] (http://railscasts.com/episodes/258-token-fields?view=asciicast). Это требует дополнительных шагов, но Райан отлично справился с этим. – Firyn