Skip to content

Instantly share code, notes, and snippets.

@xuanyu-h
Last active December 12, 2016 08:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xuanyu-h/d085686c5c4e600586229bab1fd5f584 to your computer and use it in GitHub Desktop.
Save xuanyu-h/d085686c5c4e600586229bab1fd5f584 to your computer and use it in GitHub Desktop.
ChainedList
# 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