[解決済み] railsアプリケーションでapp/services/はどのように使われているのでしょうか?
質問
Ruby on Railsのエコシステムで、時々このようなことに出くわします。
class LocalizeUrlService
class Services::UpdateUserRegistrationForOrder
class ProductionOrderEmailService
UserCart::PromotionsService.new(
Shipping::BulkTrackingService.new(bulk_update, current_spree_user)
また、例として ここで
しかし、例えば "Ruby On Rails Guides" などの公式の例では、このような例は見たことがありません。これは、Rails/OOPとは異なる別の言語/パラダイムから来た概念であると思われます。
このパラダイム/トレンドはどこから来ているのでしょうか?チュートリアルや本があるのでしょうか? この人たちは影響を受けたのでしょうか?この人たちは、数年前のSOAトレンドの生き残りなのでしょうか?
app/service/blah_service.rb にコードを置くのは良いアイデアですか? もしそうなら、どのようなロジックやコードがサービス材料とみなされるのでしょうか。 もしそうなら、どのようなロジック/コードが "Service"材料とみなされるのでしょうか?
app/servicesフォルダを作成するgem/pluginは何ですか?vanilla railsのアプリにはまず入っていません。
sidetoneです。個人的には、サービスをインスタンス化することに問題があります。クラスとインスタンス化は、多くのプログラマが間違って使っているように思います。クラスとインスタンス化は、quot;物のためであり、サービスはquot;するものであると思います。 ということで、mixin/defs/includeがいいんじゃないかと思います。
解決方法は?
サービスオブジェクトは、通常のMVCパラダイムにうまく当てはまらないもののためにあります。サービスオブジェクトは、通常、モデルやコントローラが肥大化してしまうようなビジネスロジックに使用されます。一般的に、サービスオブジェクトは状態を持たず(モデル内に保持されます)、APIや他のビジネスロジックと会話するようなことをします。サービスオブジェクトは、モデルを薄くし、集中させることができます。そして、それぞれのサービスオブジェクトも薄く、一つのことに集中します。
Railsサービスオブジェクト。包括的なガイド は、Twitterとの会話を管理するためにサービスオブジェクトを使用する例や、複数のモデルを横断するような複雑なデータベーストランザクションをカプセル化する例などがあります。
Ruby on Railsのサービスオブジェクト...そしてあなたへ は、新規ユーザー登録処理を管理するためのサービスオブジェクトを作成することを示しています。
EngineYardのブログで サービスを使ってRailsのコントローラをクリーンでDRYに保つ クレジットカード決済を行うサービスオブジェクトの例です。
原点に立ち返るなら Railsのサービスオブジェクトは、クリーンで保守性の高いコードを設計するのに役立ちます。その方法を紹介します。 は、登場したばかりの2014年のものです。
<ブロッククオートサービスには、アプリケーションのコアロジックをコントローラやモデルに分散させることなく、別のオブジェクトに集中させることができるという利点があります。
すべてのサービスに共通する特徴は、そのライフサイクルにあります。
- 入力を受け付ける
- 作業を行う
- 結果報告
もしこれが、関数が行うことに酷似していると思われるなら、その通りです。彼らはさらに
call
をサービス上のパブリックメソッド名として使用します。
プロック
. サービスオブジェクトは、大きなサブルーチンになってしまうものに名前を付けて整理する方法と考えることができます。
Railsサービスオブジェクトの構造 は、サービスオブジェクトと懸念の違いを取り上げています。また、サービスオブジェクトがモジュールよりも優れている点についても説明します。また、良いサービスオブジェクトとはどのようなものかを詳しく説明しています。
<ブロッククオート- 状態を保存しない
- クラスメソッドではなく、インスタンスメソッドを使用する
- パブリックメソッドはほとんどないほうがいい
- メソッドのパラメータは、操作されるか入力として必要とされる値オブジェクトであるべきです。
- メソッドは、ブール値ではなく、リッチな結果オブジェクトを返す必要があります。
- 依存するサービスオブジェクトは、プライベートメソッドでアクセスできるようにし、コンストラクタ内または遅延して作成する必要があります。
例えば、ユーザーをリストに登録するアプリケーションがあったとして、それは3つのモデルになるかもしれません。User、List、Subscriptionです。
class List
has_many :subscriptions
has_many :users, through: :subscriptions
end
class User
has_many :subscriptions
has_many :lists, through: :subscriptions
end
class Subscription
belongs_to :user
belongs_to :list
end
リストへのユーザーの追加と削除の処理は、基本的な
create
と
destroy
メソッドとアソシエーション、そしていくつかのコールバックがあります。
今、あなたの上司は、大規模なロギング、統計情報の追跡、SlackやTwitterへの通知、メールの送信、大規模な検証を行う、手の込んだ購読プロセスを求めています...今まではシンプルな
create
と
destroy
は、APIにコンタクトし、複数のモデルを更新する複雑なワークフローになります。
それらをすべて懸念事項やモジュールとして記述し、これら3つの元単純なモデルにそれらすべてを含めて、大きな
Subscription.register
と
Subscription.remove
というクラスメソッドがあります。これでサブスクリプションは、ツイートやSlackへの投稿、メールアドレスの確認、バックグラウンドチェックができるようになりましたね。変ですね。あなたのモデルは、コア機能とは関係のないコードで肥大化しています。
代わりに、次のように書きます。
SubscriptionRegistration
と
SubscriptionRemove
サービスオブジェクトです。これらには、統計情報をツイートして保存したり、バックグラウンドチェックを実行したりする機能などを含めることができます(というより、それをより多くのサービスオブジェクトに入れる可能性が高いです)。それぞれ1つのパブリックメソッドを持っています。
SubscriptionRegistration.perform(user, list)
と
SubscriptionRemove.perform(subscription)
. ユーザー、リスト、サブスクリプションは何も知らなくていい。あなたのモデルはスリムなまま、ひとつのことをするだけです。そして、あなたのサービスオブジェクトはそれぞれ1つのことをします。
具体的な質問ですが...
このパラダイム/トレンドはどこから来ているのか?
私が知る限り、これは「ファットモデル/スキニーコントローラー」というトレンドの帰結です。それは良いアイデアなのですが、しばしばモデルが太りすぎてしまうのです。モジュールや関係性を考慮しても、1つのクラスに詰め込むには多すぎるのです。通常モデルやコントローラを肥大化させる他のビジネスロジックは、サービスオブジェクトに入ります。
<ブロッククオートapp/servicesフォルダを作成するgem/pluginは何ですか?
するんですね。にあるものはすべて
app/
はRails 5でオートロードされます。
関連
-
[解決済み] Rails のインストールに失敗する: activesupport には Ruby のバージョン >= 2.2.2 が必要です。
-
[解決済み] レイル 4 radio_button_tag default not selected
-
[解決済み] Rails 4で懸念事項を使用する方法
-
[解決済み] RailsのERBにおける<%、<%=、<%#、-%>の違いは何ですか?
-
[解決済み】Ruby on Railsはモデルのfield:typeを生成します - field:typeのオプションは何ですか?
-
[解決済み】新規アプリケーション作成時に使用するrailsのバージョン指定について
-
[解決済み】Rails - コントローラの内部でヘルパーを使用する方法
-
[解決済み] Ruby on Railsのコールバック、:before_saveと:before_createの違いは何ですか?
-
[解決済み] Railsのモデル、ビュー、コントローラ、ヘルパー:何をどこに置くか?
-
[解決済み] Railsです。アドレスが既に使用中 - bind(2) (Errno::EADDRINUSE)
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】取得中。「プロジェクトのクローンとマイグレート後に、「マイグレーションは保留中です。この問題を解決するには 'bin/rake db:migrate RAILS_ENV=development' を実行してください。
-
[解決済み】警告:定数 ::Fixnum は非推奨 新しいモデルを生成するとき
-
[解決済み] nil:NilClass の未定義メソッド `each'... なぜでしょうか?
-
[解決済み] Railsです。NameError: 初期化されていない定数
-
[解決済み] 新規ユーザー作成時に ActiveModel::ForbiddenAttributesError が発生する。
-
[解決済み] 変更欄のRailsマイグレーション
-
[解決済み] Ruby: public static メソッドを作るには?
-
[解決済み] rspecにおけるassignsの意味
-
[解決済み] "render :nothing => true" は空のプレーンテキストファイルを返すのですか?
-
[解決済み] 属性を割り当てる場合、引数としてハッシュを渡す必要がある