2

私は持っていて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で、カテゴリがまだ存在しない場合は、別のトランザクションで新しいカテゴリが作成されます。したがって、 にエラーがあった場合でもarticle、新しいカテゴリが作成される可能性があります。

作成/更新アクションのログ (簡潔にするためにトリミングされています):

   (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

しかし、それは両方のメソッドで同じコードを書かなければならないことを意味します:createupdate. DRYの原則に違反しているため、別の方法を見つけたいと思います。

4

2 に答える 2

2
  1. 1行のコードがDRYかどうかは気にしません。
  2. 次のようなことができます

私はこれが好きではありませんが、実行可能であることに注意してください

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
于 2013-06-03T23:26:11.623 に答える