Class: Lexorank::Ranking
- Inherits:
-
Object
- Object
- Lexorank::Ranking
- Includes:
- Lexorank
- Defined in:
- lib/lexorank/ranking.rb
Constant Summary
Constants included from Lexorank
Instance Attribute Summary collapse
-
#advisory_lock_config ⇒ Object
readonly
Returns the value of attribute advisory_lock_config.
-
#field ⇒ Object
readonly
Returns the value of attribute field.
-
#group_by ⇒ Object
readonly
Returns the value of attribute group_by.
-
#original_field ⇒ Object
readonly
Returns the value of attribute original_field.
-
#original_group_by ⇒ Object
readonly
Returns the value of attribute original_group_by.
-
#record_class ⇒ Object
readonly
Returns the value of attribute record_class.
Instance Method Summary collapse
- #advisory_lock_name(instance) ⇒ Object
- #advisory_locks_enabled? ⇒ Boolean
-
#initialize(record_class:, field:, group_by:, advisory_lock:) ⇒ Ranking
constructor
A new instance of Ranking.
- #move_to(instance, position) ⇒ Object
- #validate! ⇒ Object
- #with_lock_if_enabled(instance) ⇒ Object
Methods included from Lexorank
#get_char, #mid, #value_between
Constructor Details
#initialize(record_class:, field:, group_by:, advisory_lock:) ⇒ Ranking
Returns a new instance of Ranking.
8 9 10 11 12 13 14 15 |
# File 'lib/lexorank/ranking.rb', line 8 def initialize(record_class:, field:, group_by:, advisory_lock:) @record_class = record_class @original_field = field @field = process_column_name(field) @original_group_by = group_by @group_by = process_group_by_column_name(group_by) @advisory_lock_config = { enabled: record_class.respond_to?(:with_advisory_lock) }.merge(advisory_lock) end |
Instance Attribute Details
#advisory_lock_config ⇒ Object (readonly)
Returns the value of attribute advisory_lock_config.
6 7 8 |
# File 'lib/lexorank/ranking.rb', line 6 def advisory_lock_config @advisory_lock_config end |
#field ⇒ Object (readonly)
Returns the value of attribute field.
6 7 8 |
# File 'lib/lexorank/ranking.rb', line 6 def field @field end |
#group_by ⇒ Object (readonly)
Returns the value of attribute group_by.
6 7 8 |
# File 'lib/lexorank/ranking.rb', line 6 def group_by @group_by end |
#original_field ⇒ Object (readonly)
Returns the value of attribute original_field.
6 7 8 |
# File 'lib/lexorank/ranking.rb', line 6 def original_field @original_field end |
#original_group_by ⇒ Object (readonly)
Returns the value of attribute original_group_by.
6 7 8 |
# File 'lib/lexorank/ranking.rb', line 6 def original_group_by @original_group_by end |
#record_class ⇒ Object (readonly)
Returns the value of attribute record_class.
6 7 8 |
# File 'lib/lexorank/ranking.rb', line 6 def record_class @record_class end |
Instance Method Details
#advisory_lock_name(instance) ⇒ Object
95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/lexorank/ranking.rb', line 95 def advisory_lock_name(instance) if advisory_lock_config[:lock_name].present? advisory_lock_config[:lock_name].(instance) else "#{record_class.table_name}_update_#{field}".tap do |name| if group_by.present? name << "_group_#{instance.send(group_by)}" end end end end |
#advisory_locks_enabled? ⇒ Boolean
107 108 109 |
# File 'lib/lexorank/ranking.rb', line 107 def advisory_locks_enabled? record_class.respond_to?(:with_advisory_lock) && advisory_lock_config[:enabled] end |
#move_to(instance, position) ⇒ Object
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/lexorank/ranking.rb', line 36 def move_to(instance, position) if block_given? && advisory_locks_enabled? return with_lock_if_enabled(instance) do move_to(instance, position) yield end end collection = record_class.ranked if group_by.present? collection = collection.where("#{group_by}": instance.send(group_by)) end # exceptions: # move to the beginning (aka move to position 0) # move to end (aka position = collection.size - 1) # when moving to the end of the collection the offset and limit statement automatically handles # that 'after' is nil which is the same like [collection.last, nil] before, after = if position == :last [collection.last, nil] elsif position.zero? [nil, collection.first] else collection.where.not(id: instance.id).offset(position - 1).limit(2) end # If position >= collection.size both `before` and `after` will be nil. In this case # we set before to the last element of the collection if before.nil? && after.nil? before = collection.last end rank = if (self == after && send(field).present?) || (before == self && after.nil?) send(field) else value_between(before&.send(field), after&.send(field)) end instance.send(:"#{field}=", rank) if block_given? yield else rank end end |
#validate! ⇒ Object
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
# File 'lib/lexorank/ranking.rb', line 17 def validate! if advisory_lock_config[:enabled] && !record_class.respond_to?(:with_advisory_lock) raise( Lexorank::InvalidConfigError, "Cannot enable advisory lock if #{record_class.name} does not respond to #with_advisory_lock. " \ 'Consider installing the with_advisory_lock gem (https://rubygems.org/gems/with_advisory_lock).' ) end unless @field # TODO: Make this raise an error. Supplying an invalid column should raise. warn "The supplied ranking column \"#{@original_field}\" is not a column of the model!" end if original_group_by && !group_by warn "The supplied grouping by \"#{original_group_by}\" is neither a column nor an association of the model!" end end |
#with_lock_if_enabled(instance) ⇒ Object
85 86 87 88 89 90 91 92 93 |
# File 'lib/lexorank/ranking.rb', line 85 def with_lock_if_enabled(instance, &) if advisory_locks_enabled? = advisory_lock_config.except(:enabled, :lock_name) record_class.with_advisory_lock(advisory_lock_name(instance), **, &) else yield end end |