ビジネスロジックを扱うPORO(Plain Old Ruby Object)があります。 ActiveRecord
オブジェクトを受信し、分類します。簡略化のため、一例として、以下の取る:RubyとSQLのビジネスロジックが重複しています
class Classificator
STATES = {
1 => "Positive",
2 => "Neutral",
3 => "Negative"
}
def initializer(item)
@item = item
end
def name
STATES.fetch(state_id)
end
private
def state_id
return 1 if @item.value > 0
return 2 if @item.value == 0
return 3 if @item.value < 0
end
end
しかし、私はまた、グループオブジェクトがこれらstate_id
「仮想属性」に基づいてクエリをしたいです。私は現在、SQLクエリでこの属性を作成し、それをGROUP BY
ステートメントで使用することでこれを処理しています。例を参照してください:
class Classificator::Query
SQL_CONDITIONS = {
1 => "items.value > 0",
2 => "items.value = 0",
3 => "items.value < 0"
}
def initialize(relation = Item.all)
@relation = relation
end
def count
@relation.select(group_conditions).group('state_id').count
end
private
def group_conditions
'CASE ' + SQL_CONDITIONS.map do |k, v|
'WHEN ' + v.to_s + " THEN " + k.to_s
end.join(' ') + " END AS state_id"
end
end
この方法で、私はSQLにこのビジネスロジックを取得し、非常に効率的な方法で、クエリのこの種を作ることができます。
問題は次のとおりです。ビジネスロジックが重複しています。 "ルビー"コード内に存在し、単一のオブジェクトを分類し、また "SQL"に分類して、データベースレベルのオブジェクトの集合を分類する。
これは悪い習慣ですか?これを避ける方法はありますか?私は実際には、これを行うことができた次の操作を行う:
item = Item.find(4)
items.select(group_conditions).where(id: item.id).select('state_id')
をしかし、これを行うことによって、私は、データベースに永続化されていないオブジェクトを分類する能力を失います。もう1つの方法は、Iteratorを使用してルビの各オブジェクトを分類することですが、データベースのパフォーマンスが低下します。
2つのケースの中でベストが必要な場合は、重複したビジネスロジックを維持することは避けられないようです。しかし、私はちょうどこれについて確かめたいです。 :)
ありがとう!
データベースのこのフィールドを更新すると、パフォーマンスが向上する可能性があります。しかし、私はまだビジネスロジックが重複していると思います。データベーストリガと 'state_if'メソッドの両方。 –
@JoãoDanielはい、いいえ。この方法では、ビジネスロジックが永続オブジェクトと非永続オブジェクトで絶対に同じであるかどうかにかかわらず、すべてのロジックをDBレイヤに入れ、 'start_transaction⇒read_state⇒rollback'ハックを実行することができます。 – mudasobwa