AASMGemを使用してRubyでステートマシンを作成する方法
今日は、ステートマシン、それらがどのように機能するか、AASMgemを使用したRubyプロジェクトでそれらを使用する方法について学習します。
今 :
信号機を想像してみてください…
赤、緑、黄色のいずれでもかまいません。
色が変わると、次へ 色は現在に基づいています 1つ。
これは、目の不自由な人がいつ横断できるかを知るための音を出す種類だとしましょう。
今 :
あなたはこのためのソフトウェアを書いています。
毎回再生する音と次の色をどのように知るのですか?
次のようなifステートメントを記述できます:
if @light.state == "green" @light.play_green_sound end if @light.state == "green" @light.change_to_yellow end # ...
この状態チェックコードはいたるところにあります!
どうすればこれを改善できますか?
オブジェクト指向デザインの原則を適用すると、州のデザインパターンを再発見できます。
ステートデザインパターンとは何ですか?
ステートデザインパターンは、ステートマシンを実装する1つの方法です。
3つのコンポーネントが必要です :
Context
クラス、このクラスは現在の状態が何であるかを知っていますState
クラス、このクラスは、個々の州によって実装されるべきメソッドを定義します- 州ごとに1つのクラス。これらのクラスは、
State
から継承します クラス
信号機の例では、コンテキストはTrafficLight
です。
そして、状態はGreen
、Red
&Yellow
。
すべての州が何をすべきかを知っています。
大きなメリット ?
すべての状態はそれ自体を知っているので、現在の状態をチェックする必要はありません。これは、条件文が少なくなり、複雑さの原因となることがよくあります。
信号機の実装
このパターンの実際の実装のコードを見てみましょう。
こちらがTrafficLight
です :
class TrafficLight def initialize @state = nil end def next_state(klass = Green) @state = klass.new(self) @state.beep @state.start_timer end end
これが基本のState
です :
class State def initialize(light) @light = light end def beep end def next_state end def start_timer end end
はい、これら3つの方法は空です。
この「インターフェース」を定義することは、他のプログラミング言語(Javaなど)では一般的な規則ですが、Rubyでは一般的ではありません。
これはデモンストレーションの目的でここにあります。
ただし、initialize
を共有したいのですが すべての状態がコンテキストを必要とするため、すべての状態間のメソッド (TrafficLight
オブジェクト)状態の変化を通知する 。
今 :
3つの状態は互いに非常に似ているため、そのうちの1つだけのコードを示します。
これがGreen
です 状態:
class Green < State def beep puts "Color is now green" end def next_state @light.next_state(Yellow) end def start_timer sleep 5; next_state end end
すべての州は、次の州に切り替える方法と時期を知っています。
AIゲームの例
ステートマシンを使用して、RubyWarriorなどの現在の状態に依存するゲームを解決できます。
RubyWarriorでは、プレーヤーオブジェクトとボードが提供されます。
目標は :
- ボード上のすべての敵を倒します
- HPを0より上に保ちながら出口に到達します
一度に1つの動きをすることができ、レベルを完了したい場合は適切な選択をする必要があります。
現在の状態を確認すると、その選択に役立ちます。
そのため、ステートマシンが優れたソリューションです。
ここに例があります :
class Attacking < State def play(warrior) warrior.attack! @player.set_state(Healing) unless enemy_found?(warrior) end end
これは、戦士がいる可能性のある状態の1つであり、敵が見えないときにHealing
に移動します。 戦闘ダメージから回復する状態。
AASMGemの使用
遷移が有効であることを確認しながら現在の状態を追跡したい場合は、AASMのようなステートマシンの宝石を使用できます。
この宝石は、イベントのアイデアに基づいて構築されています (ライトスイッチを押すなど)トリガーが他の状態に移行します。
ここに例があります :
require 'aasm' class Light include AASM aasm do state :on, :off event :switch do transitions :from => :on, :to => :off, :if => :on? transitions :from => :off, :to => :on, :if => :off? end end end
このクラスの使用方法 :
light = Light.new p light.on? # true light.switch p light.on? # false
このステートマシンを使用すると、現在の状態が「オフ」の場合にのみ「オン」状態に移行できます。状態遷移中に特定のコードを実行するために、(前/後の)いくつかのコールバックを持つこともできます。
これらのコールバック 次のようなものを含めることができます:
- メールの送信
- 状態変化をログに記録する
- ライブモニタリングダッシュボードの更新
さらに、AASMには、ActiveRecord
を使用して現在の状態をデータベースに保存するオプションがあります。 。
AASMジェムビデオ
概要
ステートマシン、ステートデザインパターン、AASMジェムについて学びました。私のRubyニュースレター(7000人以上の購読者)を購読して、今すぐ学習を続けてください。新しい記事と購読者限定のRubyのヒントをお見逃しなく 。
今度は、これらの新しいアイデアを使って練習しましょう🙂
読んでくれてありがとう!
-
Ruby Mapメソッドの使用方法(例付き)
Mapは、配列、ハッシュ、範囲で使用できるRubyメソッドです。 マップの主な用途は、データを変換することです。 例 : 文字列の配列が与えられた場合、すべての文字列に目を通し、すべての文字を大文字にすることができます。 または、Userのリストがある場合 オブジェクト… 変換できます 対応するメールアドレス、電話番号、またはその他の属性のリストにそれらを追加します Userで定義 クラス。 これを行う方法を正確に見てみましょう! ルビーマップ構文 マップの構文は次のようになります: array = [a, b, c] array.map { |string| string.
-
Rubyの配列クラスの使用方法(例+便利なメソッド)
アレイとは何ですか? 配列は組み込みのRubyクラスであり、0個以上のアイテムのリストを保持します 、およびこれらすべてのアイテムを簡単に追加、アクセス、およびループするのに役立つメソッドが含まれています。 配列が存在しない場合は多くの変数を使用する必要があるため、これは便利です。 例 : a =1b =2c =3 しかし、代わりに、あなたはそうすることができます : 番号=[1、2、3] 最良の部分は? 配列内には何でも入れることができます! いいね : 数字 文字列 より多くのアレイ! (それは多次元配列になります) アレイを最大限に活用できるように、アレイについ