Created
May 18, 2011 16:03
-
-
Save robertsosinski/978879 to your computer and use it in GitHub Desktop.
A sequel plugin that allows positioning with options.
This file contains hidden or 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
| 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