Tag
さまざまな種類のタグが存在する抽象的な概念を考えてみましょうTopic
。Location
タグであること以外は無関係です。これらは共通の基本Tag
プロパティを持ちますが、それ以外は異なります。
コンセプトは類似のコンセプトTopic
に基づいていTag
ます。のような操作Topic::Update
は通常 から継承しTopic::Create
ますが、そのような操作も から継承する必要がありますTag::Update
。Ruby は多重継承をサポートしていません。Trailblazer はこれをサポートできますか?
Trailblazer の操作は、提供されたハッシュ
builds
の内容に基づいてサブクラスをインスタンス化できるブロックによる継承をサポートします。params
これは、基本クラス (Tag
) が公開されており、基本クラスを介して操作が呼び出される場合に機能します。ただし、この例では、公開クラスはTopic
サブクラスです。操作はサブクラス ( ) を介して呼び出す必要があります
Topic
が、その操作は共通のTag
基本クラス (リバース ビルダー?) に基づいています。
これは、単一の継承によって実現できる 1 つの方法です (ただし、このアプローチの欠点を示しています)...
各タイプのタグは独自のデータベース テーブルに格納され、次のような ActiveRecord クラスがあります。
class Tag < ActiveRecord::Base
self.abstract_class = true
end
class Topic < Tag; end
Trailblazer の概念は同様の設計に従います。Tag
操作は基本機能を提供し、より具体的な操作によってサブクラス化されます ( Topic
)。Tag
操作は直接使用されません。Topic
たとえば、コントローラーがTopic
操作を使用します。
操作はTopic
から継承しますが、各操作内でのみ可能と思われるTag
独自のモデルを指定する必要があり、それぞれを明示的にサブクラス化する必要があります。Topic
class Topic < Tag
class Create < Tag::Create
model Topic
end
class Update < Tag::Update
model Topic
end
class Delete < Tag::Delete
model Topic
end
end
これに関する問題は、基本操作で定義されているコントラクトが、それを aTag
ではなく a であるTopic
と見なし、モデルとして使用される場合に問題が発生することです。これがどこに問題があるかを示す例は、セルのビューにTopic
あります。概念には、オブジェクトを操作するためのビューを提示するセルがあります。simple_form_for
次のように、を使用してフォームをレンダリングします。
simple_form_for operation.contract
コントラクトはそれTag
を
- そのパラメータは
params[:tag]
代わりにとして送信されますparams[:topic]
- 送信ボタンのラベルはCreate TopicではなくCreate Tagです。
operation.model
送信された操作が失敗した後にレンダリングするときにフォームエラーが表示されないため、セルは使用できません(それ以外の場合は機能します)。
これを解決する方法は、次のように明示することsimple_form_for
です。
simple_form_for operation.contract, as: :topic, url: topics_path ...
プロパティを に追加する場合、コントラクトTopic
を拡張する必要があるため、別の問題が発生します。Tag
これを行う通常の方法はcontract do..end
、操作にブロックを追加することTopic::Create
です。問題が発生するのは、そのようなブロックが および からではなく対応するブロックから継承さTopic::Update
れてTopic::Delete
いるためです。Tag
Topic::Create
別の方法は、サブクラス化されたTopic::Update
操作を から継承することTopic::Create
です。これにより、モデルを指定する必要がなくなりますが (指定するため)、操作Topic::Create
によって追加されたものはすべて失われます。Tag::Update
class Update < Create
action :update
end
は継承されていないため再指定する必要がありますが、 は継承されているため、action
で追加されたプロパティは で使用できます。Tag::Update
Topic::Create
Topic::Create
Topic::Update
これらのスタイルはどちらも、変更が 1 つの基本クラスのみにある限り機能します。Rubyは多重継承をサポートしていないため、両方に変更があると壊れます。Delete
通常は次のような操作を考えてみましょう。
class Delete < Create
action :find
def process(params)
# validate params and then delete
end
end
もしそうなら、どちらかである可能性がありTag::Delete
ますTopic::Delete
class Delete < Tag::Delete
model Topic
end
また
class Delete < Create
action :find
end
前者の場合、Topic::Delete
は によって追加されたプロパティを認識せずTopic::Create
、後者の場合は で定義されたメソッドTopic::Delete
を欠いています。process
Tag::Delete
Trailblazer の概念が別の概念を継承し、その操作を拡張するにはどうすればよいでしょうか?