Last active
December 12, 2016 08:03
-
-
Save xuanyu-h/d085686c5c4e600586229bab1fd5f584 to your computer and use it in GitHub Desktop.
ChainedList
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# a project have many steps | |
class Step | |
module ChainedList | |
extend ActiveSupport::Concern | |
included do | |
# DNode | |
field :prior_step_id, type: BSON::ObjectId | |
field :next_step_id, type: BSON::ObjectId | |
end | |
# Usage: next_step_without_database | |
# use Enumerable#find | |
def next_step(list) | |
return unless has_next_step? | |
list.find { |i| i.id.to_s == next_step_id.to_s } | |
end | |
def update_chain_data_before_destroy | |
if is_top_step? && next_step | |
n = next_step | |
project.update_attribute(:first_step_id, n.id) | |
n.update_attribute(:prior_step_id, nil) | |
elsif prior_step | |
p = prior_step | |
p.update_attribute(:next_step_id, next_step_id) | |
if next_step | |
n = next_step | |
n.update_attribute(:prior_step_id, p.id) | |
end | |
end | |
end | |
# Usage: next_step or next_step_with_database | |
def next_step_with_database | |
return unless has_next_step? | |
Step.find(next_step_id.to_s) | |
end | |
alias_method_chain :next_step, :database | |
# Usage: prior_step_without_database | |
# use Enumerable#find | |
def prior_step(list) | |
return unless has_prior_step? | |
list.find { |i| i.id.to_s == prior_step_id.to_s } | |
end | |
# Usage: prior_step or prior_step_with_database | |
def prior_step_with_database | |
return unless has_prior_step? | |
Step.find(prior_step_id.to_s) | |
end | |
alias_method_chain :prior_step, :database | |
def has_next_step? | |
!!next_step_id | |
end | |
def has_prior_step? | |
!!prior_step_id | |
end | |
def is_top_step? | |
project.first_step_id.to_s == id.to_s | |
end | |
def is_bottom_step? | |
!has_next_step? | |
end | |
class_methods do | |
def update_chain_data_after_create(project, target_id, step) | |
if target = find(target_id.to_s) | |
step.project = project | |
step.prior_step_id = target_id | |
if next_step = target.next_step | |
step.next_step_id = next_step.id | |
next_step.update_attribute(:prior_step_id, step.id) | |
end | |
target.update_attribute(:next_step_id, step.id) | |
else | |
step.project = project | |
if first_step = project.first_step # if first_step is exist? | |
step.next_step_id = first_step.id | |
first_step.update_attribute(:prior_step_id, step.id) | |
end | |
project.update_attribute(:first_step_id, step.id) | |
end | |
step.save && step.reload | |
step | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment