Module: PagedScopes::Index

Defined in:
lib/paged_scopes/index.rb

Instance Method Summary collapse

Instance Method Details

#after(object) ⇒ Object



42
43
44
45
46
47
48
49
# File 'lib/paged_scopes/index.rb', line 42

def after(object)
  after_index = index_of(object) + 1
  if limit = scope(:find, :limit)
    after_index >= limit ? nil : first(:offset => after_index + (scope(:find, :offset) || 0))
  else
    first(:offset => after_index)
  end
end

#before(object) ⇒ Object



51
52
53
54
55
56
57
58
# File 'lib/paged_scopes/index.rb', line 51

def before(object)
  before_index = index_of(object) - 1
  if scope(:find, :limit)
    before_index < 0 ? nil : first(:offset => before_index + (scope(:find, :offset) || 0))
  else
    before_index < 0 ? nil : first(:offset => before_index)
  end
end

#index_of(object) ⇒ Object



3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/paged_scopes/index.rb', line 3

def index_of(object)
  columns = scope(:find, :order).to_s.split(',').map(&:strip) << "#{table_name}.#{primary_key}"
  operators = columns.map do |column|
    column.slice!(/\s+(asc|ASC)$/)
    column.slice!(/\s+(desc|DESC)$/) ? ">" : "<"
  end
  
  attributes = (1..columns.size).map { |n| "attribute_#{n}" }
  
  selects = [ columns, attributes ].transpose.map do |column, attribute|
    "#{column} AS #{attribute}"
  end.unshift("#{table_name}.*").join(', ')
  
  options = { :select => selects }
  options.merge!(:offset => 0) if scope(:find, :limit) && scope(:find, :offset)
  object_with_attributes = find(object.id, options)

  values = attributes.map { |attribute| object_with_attributes.send(attribute) }
  
  string, hash = "", {}
  [ columns, operators, attributes, values ].transpose.reverse.each do |column, operator, attribute, value|
    string = string.blank? ?
      "#{column} #{operator} :#{attribute}" :
      "#{column} #{operator} :#{attribute} OR (#{column} = :#{attribute} AND (#{string}))"
    hash.merge!(attribute.to_sym => value)
  end
  
  options = { :conditions => [ string, hash ], :distinct => true }
  options.merge!(:offset => 0) if scope(:find, :limit) && scope(:find, :offset)
  before_count = count("#{table_name}.#{primary_key}", options)
  
  if scope(:find, :limit)
    before_count -= scope(:find, :offset) if scope(:find, :limit) && scope(:find, :offset)
    raise ActiveRecord::RecordNotFound, "Couldn't find #{name} with ID=#{object.id}" if before_count < 0 || before_count >= scope(:find, :limit)
  end
  
  before_count
end