あなたのコードはどこに行きますか?
Railsチュートリアルを終了して独自のアプリを起動すると、混乱が生じます。非CRUDの一般的なロジックはどこに行くのですか? Twitterからフォロワーを獲得することはMVCにどのように適合しますか? 2人に聞いてみると、4つの答えが得られます。または、あなたが机に頭をぶつけている間、あなたのスレッドは何時間もお互いを侮辱する賢い人々の束に発展します。いずれにせよ、あなたは頭痛の種になります。
夢見ていたアプリを作成するには、いくつかが必要です。 一般的な、Rails以外のロジック。 では、コードをどこに配置し、それでも物事をシンプルに保つのでしょうか?
既存のActiveRecordモデルに関連していると感じるロジックがある場合は、まずそのモデルに配置します。 たとえば、ゲーム
がある場合 モデルであり、CSVファイルから多数のゲームをインポートしたかったので、そのメソッドを Game
に直接配置しました。 クラス:
class Game < ActiveRecord::Base
def self.parse_from_csv(csv_string)
games = []
CSV.parse(csv_string, quote_char: "'") do |row|
games << Game.from_csv_row(row) if (row[0] == 'G')
end
games
end
def self.from_csv_row(row)
Game.new({
dgs_game_id: row[1],
opponent_name: row[2],
created_at: row[4],
updated_at: row[4],
})
end
end
メソッドに必要なすべての情報が手元にあります。簡単にテストできます。そして、おそらく新しい寄稿者が最初にそのロジックを探す場所です。
ただし、そのモデルを追加および変更し続けると、大きく複雑になります。モデルのさまざまな部分が奇妙な方法で相互作用します。 変更すればするほど、変更が難しくなります。
その場合、おそらくそのコードを非ActiveRecordモデルにリファクタリングすることをお勧めします。
Railsアプリにあるからといって、アクティブ/アクションから継承する必要があるという意味ではありません。
プレーンなRubyオブジェクトで独自のRubyコードを記述し、それらをRailsアプリで使用できます。 これらのオブジェクトは、問題の一部をモデル化しているため、引き続きモデルと呼ぶことができます。データを保存するActiveRecordデータベースがないだけです。
次回そのゲームのCSVパーサーに取り組んだときは、 Game
クラスが少し大きくなりすぎていました。そこで、パーサーロジックを独自の GameCSVParser
に移動しました クラス。
コミット全体はここにありますが、これは非ActiveRecordクラスがどのように見えるかです:
class GameCSVParser
def initialize(csv_string)
@rows = CSV.parse(csv_string, quote_char: "'")
end
def games
game_rows.map { |row| Game.new(game_attributes(row)) }
end
private
def game_rows
@rows.select { |row| is_game_row?(row) }
end
def game_attributes(row)
{
dgs_game_id: row[1],
opponent_name: row[2],
created_at: row[4],
updated_at: row[4],
}
end
def is_game_row?(row)
row[0] == 'G'
end
end
追加するロジックが特定のActiveRecordモデルに関連していると思われない場合は、新しいプレーンなRubyオブジェクトの作成に進みます。または、コードがアプリにまだ存在していないものの一部であると思われる場合。それ以外の場合は、ほとんどの場合、リファクタリングによってポップアップします。
プレーンなRubyオブジェクトを使用すると、何でも書くことができます。しかし、あなたが何でも書くことができることを知っている 方向性については役に立ちません。どのような方法が必要ですか?すべての新しいオブジェクトはどのように相互作用しますか?
多くのRailsアプリは同じカテゴリを使用します プレーンなRubyオブジェクトの。 これらのカテゴリは、他の開発者が認識できるコードを作成するために従うことができるパターンです。すでにいくつか聞いたことがあるかもしれません。
サービスオブジェクト、プレゼンター、およびジョブ
サービスオブジェクト、プレゼンター、およびジョブについて特別なことは何もありません。これらは、特定の認識可能な方法で動作する単なるRubyオブジェクトです。
たとえば、Resqueジョブ はperform
を持つプレーンなRubyクラスです メソッドと@queue
:
class FetchGamesForPlayer
@queue = :default
def self.perform(player_id)
player = Player.scoped_by_id(player_id).ready_for_fetching.first
player && player.fetch_new_games!
end
end
実行コード> ジョブの実行時に呼び出されます。
プレゼンター ビュー内でのみ意味のあるコードを持つプレーンなRubyオブジェクトです:
class UserPresenter
def show_related_users?
@user.related.count > 3
end
end
また、Railsのビューヘルパーが含まれている場合や、いくつかの異なるオブジェクトを取得して、ビューの利便性のためにそれらを1つの統合オブジェクトとして扱う場合もあります。
サービスオブジェクト 実行するプロセスを表すプレーンなRubyオブジェクトです。たとえば、投稿にコメントを書くと、次のようになります。
- コメントを残してください。
- 投稿の作成者に通知メールを送信します。
サービスオブジェクトは両方を実行し、そのロジックをコントローラーから遠ざけることができます。
ここでは、サービスオブジェクトについて優れた見解があります。例がたくさんあります。
単純なプロセスの場合、サービスオブジェクトを気にしません。 ただし、コントローラーが重くなり始めた場合は、追加のロジックを配置するのに適した場所です。
これらのパターンを使用して、独自のビジネスロジックを整理できます。これらは単なるRubyオブジェクトですが、特定のフレーバーを共有し、名前があり、他の開発者と話し合うことができるRubyオブジェクトです。
どこから始めますか?
Rails以外のビジネスロジックが進む可能性のある場所はたくさんあります。選ぶのは難しいかもしれません。これが私がすることです:
- ロジックが既存のクラスにほとんど関連している場合、それがActiveRecordモデルであっても、私はそれをそのクラスに入れます。
- 既存のクラスに適合しない場合は、ロジックを保持するための新しいプレーンRubyクラスを作成します。
- ロジックがまだ存在していないものの一部であると思われる場合は、そのための新しいプレーンなRubyクラスを作成します。
- 後でコードに戻ってモデルが複雑になりすぎたり、そのモデルでコードが意味をなさなくなったりした場合は、コードを独自のプレーンなRubyクラスにリファクタリングします。
- コードがビューでのみ意味をなす場合は、ヘルパーに追加するか、プレゼンターを作成します。
- コードをHTTPリクエスト中に実行する必要がない場合、またはバックグラウンドで実行する必要がある場合、コードはジョブに含まれます。
- プロセスのいくつかの異なるモデルまたはステージを調整していて、コントローラーが理解しにくい場合は、それをサービスオブジェクトに入れます。
君はどうでしょう?あなたのコードはどこに行きますか?そして、これら以外に役立つと思ったパターンはありますか? コメントを残して私に知らせてください。
まだプロセスがない場合は、私のものを試してください。それがあなたにどのように合うかを見てください。コードを書くための完璧な方法はありませんが、行き詰まったときは、このようなプロセスを開始するのに役立ちます。
-
基本的なOOP原則を使用してRubyコードを劇的に改善する方法
最も重要なオブジェクト指向の原則の2つは、凝集度と結合度です。 結束 クラス内のすべてのメソッド間の関係についてです。それらは同じインスタンス変数とパラメータのセットを使用しており、すべてが同じ目標に向かって協力しています ?それとも、すべての方法が互いに分離していると感じますか? カップリング クラスが他のクラスにどの程度依存しているか、システムの他の部分にどの程度「結びついている」か、そしてこのクラスを単独で使用できるかどうかです。 これらの概念は両方とも、特定のレンズのセットを通してコードベースのすべてのクラスを確認するのに役立ちます。これらのレンズは、クラスのデザインがどれ
-
MRIソースコードの調査
しばらくRubyを使用している場合は、内部でいくつかのものがどのように機能するかについて興味があるかもしれません。 Rubyの内部を深く掘り下げる1つの方法は、Rubyを機能させるソースコードを読み取ることです。 Cを知らなくても、面白いものをいくつか拾うことができます。 ソースコードは、Rubyのgithubリポジトリにあります。 理想的には、クラス名とメソッド名を簡単に見つけることができるCodequeryのようなツールを使用する必要があります。 コアクラスの調査 ほとんどの探索はルートフォルダで行われます。ここに、Objectなどのすべてのコアクラスのソースコードがあります。 o