Skip to content

Instantly share code, notes, and snippets.

@robertsosinski
Created May 18, 2011 16:03
Show Gist options
  • Select an option

  • Save robertsosinski/978879 to your computer and use it in GitHub Desktop.

Select an option

Save robertsosinski/978879 to your computer and use it in GitHub Desktop.
A sequel plugin that allows positioning with options.
module Sequel
module Plugins
module Positioning
def self.apply(model, options = {})
options[:field] ||= :position
field = options[:field]
scope = options[:scope]
if scope
model.dataset.order!(scope, field)
else
model.dataset.order!(field)
end
model.instance_eval <<-CODE
def positioning_options
#{options.inspect}
end
CODE
end
module InstanceMethods
def move_to(p, s = scope_value)
new_position = p.to_i
new_scope_value = s && s.to_i
current_position = position_value
current_scope_value = scope_value
raise "Moving too far up" if new_position < 0
raise "Moving too far down" if new_position > last_position_value
db.transaction do
if new_scope_value == current_scope_value
case
when new_position < current_position
ds = self.class.dataset.filter("? >= ? AND ? < ?", position_field, new_position, position_field, current_position)
ds = ds.filter(scope_field => scope_value) if scope_field
ds.update(position_field => %Q{"#{position_field}" + 1}.lit)
when new_position > current_position
ds = self.class.dataset.filter("? > ? AND ? <= ?", position_field, current_position, position_field, new_position)
ds = ds.filter(scope_field => scope_value) if scope_field
ds.update(position_field => %Q{"#{position_field}" - 1}.lit)
else
return self
end
update(position_field => new_position)
else
ds = self.class.dataset.filter("? > ? AND ? = ?", position_field, current_position, scope_field, current_scope_value)
ds.update(position_field => %Q{"#{position_field}" - 1}.lit)
ds = self.class.dataset.filter("? >= ? AND ? = ?", position_field, new_position, scope_field, new_scope_value)
ds.update(position_field => %Q{"#{position_field}" + 1}.lit)
update(position_field => new_position, scope_field => new_scope_value)
end
end
end
def before_create
super
@values[position_field] = (last_position_value ? (last_position_value + 1) : 0)
end
def after_destroy
super
ds = self.class.dataset.filter("? > ?", position_field, position_value)
ds = ds.filter(scope_field => scope_value) if scope_field
ds.update(position_field => %Q{"#{position_field}" - 1}.lit)
end
private
def position_field
self.class.positioning_options[:field]
end
def position_value
@values[position_field]
end
def scope_field
self.class.positioning_options[:scope]
end
def scope_value
scope_field && @values[scope_field]
end
def last_position_value
ds = self.class.dataset
ds = ds.filter(scope_field => scope_value) if scope_field
ds.max(position_field)
end
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment