dylanninin/tower-events

开发:events 实现

Closed this issue · 4 comments

主要利用 rails 提供的机制:

  • callbacks: 实现生成 event 的 同步回调
  • concerns:DRY,减少重复代码;并尝试将 event 抽象成 DSL,降低代码入侵与耦合

ref

Todo 为例,没有 events 动态之前:

class Todo < ApplicationRecord
  enum status: { open: 0, running: 1, paused: 2, completed: 3 }

  belongs_to :assignee, class_name: 'User', optional: true
  belongs_to :todo_list
  belongs_to :project
  belongs_to :team
  belongs_to :creator, class_name: 'User'
end

要增加 创建完成events动态,需要 include Eventable,并:

class Todo < ApplicationRecord
  include Eventable
  eventablize_serializer_attrs :name
  eventablize_ops_context :create, provider: :project
  eventablize_ops_context :destroy
  # FIXME: For consistency, set_due rename to set_due_to
  eventablize_ops_context :update, verb: :set_due_to, attr: :due_to
  eventablize_ops_context :update, verb: :assign, target: :assignee, attr: :assignee_id, old_value: -> (v) { v.nil? }, new_value: -> (v) { v.present? }
  eventablize_ops_context :update, verb: :reassign, target: :assignee, attr: :assignee_id
  eventablize_ops_context :update, verb: :run, attr: :status, new_value: -> (v) { v == 'running' }
  eventablize_ops_context :update, verb: :pause, attr: :status, new_value: -> (v) { v == 'paused' }
  eventablize_ops_context :update, verb: :complete, attr: :status, new_value: -> (v) { v == 'completed' }
  eventablize_ops_context :update, verb: :reopen, attr: :status, old_value: -> (v) { v == 'completed' },  new_value: -> (v) { v == 'open' }
  eventablize_ops_context :update, verb: :recover, attr: :deleted_at, old_value: -> (v) { v.present? },  new_value: -> (v) { v.nil? }

  enum status: { open: 0, running: 1, paused: 2, completed: 3 }

  belongs_to :assignee, class_name: 'User', optional: true
  belongs_to :todo_list
  belongs_to :project
  belongs_to :team
  belongs_to :creator, class_name: 'User'
end

Todo 完成了基本的 model 测试用例,见 https://github.com/dylanninin/tower-events/blob/57eb200e6f0a2ff017037788e86b2630b1b0d5b8/spec/models/todo_spec.rb

相比系统设计 #2 中的主要变化:

  • verb 变化:set_due 调整为 set_due_to,与 tododue_to 保持一致
  • audited 单独封装成一个 hash,event[object][audited] 如:
"audited": {
"attribute": "due_to",
"old_value": nil,
"new_value": "2017-06-03"
}

需要完善的地方:

  • audited 中需要获取引用对象,而非 id 值。如 todo.assignee,指定任务的完成者时,此时保存的 audited 信息如下:
"audited": {
"attribute": "assignee_id",
"old_value": nil,
"new_value": 1
}
  • create 时,是否也可以支持其他 event 的创建,比如新建 todo 时,同时制定了完成者、完成时间。此时需要 eventablize_ops_context 调整内部实现

@zchar 目前 Todo 大致实现了如上的动态,可以 review 下,提一些意见和建议。

忘记补充一个问题,软删除时,没有调用 destroy callback。一会儿使用 update 配合 verb old_value new_value 试试