12/08/2018, 15:09

Gem State Machine

I. Giới thiệu State Machine làm cho việc quản lý trạng thái của đối tượng trở nên đơn giản. Thông thường, trạng thái của một đối tượng được giữ lại bằng cách tạo ra nhiều thuộc tính boolean và quyết định trạng thái của nó thông qua các giá trị. Điều này có thể trở nên cồng kềnh và khó khăn ...

I. Giới thiệu

  • State Machine làm cho việc quản lý trạng thái của đối tượng trở nên đơn giản. Thông thường, trạng thái của một đối tượng được giữ lại bằng cách tạo ra nhiều thuộc tính boolean và quyết định trạng thái của nó thông qua các giá trị. Điều này có thể trở nên cồng kềnh và khó khăn để xử lý khi sự phức tạp của trạng thái đối tượng của bạn bắt đầu tăng lên.

  • State_machine đơn giản hóa thiết kế này bao gồm các trạng thái, sự kiện, chuyển tiếp và gọi lại. Tuy nhiên, api được thiết kế để đơn giản như vậy bạn thậm chí không cần phải biết những gì nó thực hiện.

  • Một số tính năng ngắn, cấp cao bao gồm:

    • Defining state machines on any Ruby class
    • Multiple state machines on a single class
    • Namespaced state machines
    • before/after/around/failure transition hooks with explicit transition requirements
    • Integration with ActiveModel, ActiveRecord, DataMapper, Mongoid, MongoMapper, and Sequel
    • State predicates
    • State-driven instance / class behavior
    • State values of any data type
    • Dynamically-generated state values
    • Event parallelization
    • Attribute-based event transitions
    • Path analysis
    • Inheritance
    • Internationalization
    • GraphViz visualization creator
    • YARD integration (Ruby 1.9+ only)
    • Flexible machine syntax

II. Sử dụng

class Order < ActiveRecord::Base
  state_machine :order_status, initial: :new do
    event :add_shipment_address do
      transition [:new, :confirm] => :shipment_address
    end

    event :confirm do
      transition [:new, :shipment_address] => :confirm
    end

    event :not_deliver do
      transition [:confirm, :in_progress] => :not_deliver
    end

    event :in_progress do
      transition [:not_deliver, :already_deliver] => :in_progress
    end

    event :already_deliver do
      transition [:in_progress, :recieved_products] => :already_deliver
    end

    event :recieved_products do
      transition [:already_deliver] => :recieved_products
    end
  end
end
[2] pry(main)> order = Order.last
[3] pry(main)> order.order_status
=> "recieved_products"
[4] pry(main)> order.recieved_products?
=> true
[5] pry(main)> order.already_deliver
=> true
[6] pry(main)> order.already_deliver?
=> true
[7] pry(main)> order.confirm
=> false
[8] pry(main)> order.in_progress
=> true
[9] pry(main)> order.in_progress?
=> true
  • Vi dụ trạng thái order của bạn là in_progress Theo định nghĩa của state_machine trên thì chỉ có thể truyển về 2 trạng thái là : already_deliver và not_deliver, ta cùng kiểm tra
[15] pry(main)> order.can_confirm?
=> false
[16] pry(main)> order.can_in_progress?
=> false
[17] pry(main)> order.can_recieved_products?
=> false
[18] pry(main)> order.can_already_deliver?
=> true
[19] pry(main)> order.can_not_deliver?
=> true

Add method cho từng trạng thái

    state :not_deliver do
      def test_method
        0
      end
    end

    state :in_progress, :recieved_products do
      def test_method
        100
      end
    end

Kết quả:

[2] pry(main)> order.order_status
=> "in_progress"
[3] pry(main)> order.test_method
=> 100
[4] pry(main)> order.not_deliver
=> true
[5 pry(main)> order.order_status
=> "not_deliver"
[6 pry(main)> order.test_method
=> 0
    state all - :not_deliver do
      def test?
        true
      end
    end

    state :not_deliver do
      def test?
        false
      end
    end
[2] pry(main)> order.order_status
=> "not_deliver"
[3] pry(main)> order.test?
=> false
[4 pry(main)> order.in_progress
=> true
[5 pry(main)> order.order_status
=> "in_progress"
[6 pry(main)> order.test?
=> true
0