コントローラーから静的メソッドを呼び出し、そのクラスのインスタンスを更新する - AR::Association::HasOneAssociation の未定義メソッドを取得する
概要
私の質問:
正しい構造はどのようなものであるべきでしょうか?これを何度か再設計しようとしましたが、密結合の問題が発生し続けます。
関連情報:
いくつかのサードパーティ ソフトウェア用の新しいエンドポイントを作成しています。 ペイロードを受け取り、それを Subscription クラスの静的メソッドに渡します。 そこから、ペイロード関連のサブスクリプションを検索し、そのインスタンスを確立して、クラスの残りの情報に基づいて更新を実行したいと考えています。次のようなエラーが発生します: ActiveRecording::Association::HasOneAssociation のメソッド更新が未定義です
エンドポイントコントローラー:
class Api::V2::EndpointController < Api::V5::BaseController
def connect
data = decode(request.body.read)
Subscription.static_method(data)
end
end
サブスクリプションモデル:
class Subscription < ActiveRecord::Base
def self.static_method(data)
@subscription = Subscription.find_by_id(data.subscription_id)
@subscription.update(data)
end
end
サブスクリプションコントローラー:
class SubscriptionsController < ApplicationController
def update
#execute update
end
end
解決策
コードをモデルに移動することは、最初からあまり良いアイデアではありませんでした。更新が成功したかどうかを確認し、それに応じて応答する必要があるのはコントローラーです。モデルには、渡されたもの以外のコンテキストの概念がなく、すでに多大な責任を負っています。
可能な限り最も単純な方法で、このコードをコントローラーに書き込むだけです。
# @todo setup the correct inflections in config/initializers/inflections.rb
# @see https://github.com/rubocop/ruby-style-guide#camelcase-classes
# @see https://github.com/rubocop/ruby-style-guide#namespace-definition
module API
module V2
# @todo Write a high level description of the what the responsibility of this class is.
# the name itself is pretty smelly.
# "Endpoint" is very vague - every controller method is an endpoint.
# Why is this inheriting from a different version of the API? Very smelly.
class EndpointController < API::V5::BaseController
# @todo write a description of the purpose of this method
# @todo document the route that this method corresponds to
def connect
data = decode(request.body.read) # WTF is this?
# .find will raise an exception if the id is not valid
# Rails will catch this and return a 404.
subscription = Subscription.find(data.subscription_id)
# When you assume, you make an ass out of you and me.
# Always check if the update is successful
if subscription.update(data)
head :ok # or provide some other response
else
head :unprocessable_entity
end
end
end
end
end
後でこのコードを 2 回以上繰り返していることがわかった場合は、サービス オブジェクトなどの抽象化を追加してください。