class FriendlyId::SequentiallySlugged::Calculator
Attributes
scope[RW]
sequence_separator[RW]
slug[RW]
slug_column[RW]
Public Class Methods
new(scope, slug, slug_column, sequence_separator, base_class)
click to toggle source
# File lib/friendly_id/sequentially_slugged/calculator.rb, line 6 def initialize(scope, slug, slug_column, sequence_separator, base_class) @scope = scope @slug = slug table_name = scope.connection.quote_table_name(base_class.arel_table.name) @slug_column = "#{table_name}.#{scope.connection.quote_column_name(slug_column)}" @sequence_separator = sequence_separator end
Public Instance Methods
next_slug()
click to toggle source
# File lib/friendly_id/sequentially_slugged/calculator.rb, line 14 def next_slug slug + sequence_separator + next_sequence_number.to_s end
Private Instance Methods
conflict_query()
click to toggle source
# File lib/friendly_id/sequentially_slugged/calculator.rb, line 20 def conflict_query base = "#{slug_column} = ? OR #{slug_column} LIKE ?" # Awful hack for SQLite3, which does not pick up '\' as the escape character # without this. base << " ESCAPE '\\'" if /sqlite/i.match?(scope.connection.adapter_name) base end
last_sequence_number()
click to toggle source
# File lib/friendly_id/sequentially_slugged/calculator.rb, line 32 def last_sequence_number # Reject slug_conflicts that doesn't come from the first_candidate # Map all sequence numbers and take the maximum slug_conflicts .reject { |slug_conflict| !regexp.match(slug_conflict) } .map { |slug_conflict| regexp.match(slug_conflict)[1].to_i } .max end
next_sequence_number()
click to toggle source
# File lib/friendly_id/sequentially_slugged/calculator.rb, line 28 def next_sequence_number last_sequence_number ? last_sequence_number + 1 : 2 end
ordering_query()
click to toggle source
Return the unnumbered (shortest) slug first, followed by the numbered ones in ascending order.
# File lib/friendly_id/sequentially_slugged/calculator.rb, line 43 def ordering_query "#{sql_length}(#{slug_column}) ASC, #{slug_column} ASC" end
regexp()
click to toggle source
# File lib/friendly_id/sequentially_slugged/calculator.rb, line 47 def regexp /#{slug}#{sequence_separator}(\d+)\z/ end
sequential_slug_matcher()
click to toggle source
# File lib/friendly_id/sequentially_slugged/calculator.rb, line 51 def sequential_slug_matcher # Underscores (matching a single character) and percent signs (matching # any number of characters) need to be escaped. While this looks like # an excessive number of backslashes, it is correct. "#{slug}#{sequence_separator}".gsub(/[_%]/, '\\\\\&') + "%" end
slug_conflicts()
click to toggle source
# File lib/friendly_id/sequentially_slugged/calculator.rb, line 58 def slug_conflicts scope .where(conflict_query, slug, sequential_slug_matcher) .order(Arel.sql(ordering_query)).pluck(Arel.sql(slug_column)) end
sql_length()
click to toggle source
# File lib/friendly_id/sequentially_slugged/calculator.rb, line 64 def sql_length /sqlserver/i.match?(scope.connection.adapter_name) ? "LEN" : "LENGTH" end