Class: Simple::SQL::Scope

Inherits:
Object
  • Object
show all
Defined in:
lib/simple/sql/scope.rb

Overview

The Simple::SQL::Scope class helps building scopes; i.e. objects that start as a quite basic SQL query, and allow one to add sql_fragments as where conditions.

Defined Under Namespace

Modules: PageInfo

Constant Summary collapse

SELF =
self

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(sql) ⇒ Scope

Build a scope object



20
21
22
23
24
25
# File 'lib/simple/sql/scope.rb', line 20

def initialize(sql)
  @sql = sql
  @args = []
  @filters = []
  @order_by = nil
end

Instance Attribute Details

#argsObject (readonly)

Returns the value of attribute args.



15
16
17
# File 'lib/simple/sql/scope.rb', line 15

def args
  @args
end

#order_by_fragmentObject (readonly)

Returns the value of attribute order_by_fragment.



17
18
19
# File 'lib/simple/sql/scope.rb', line 17

def order_by_fragment
  @order_by_fragment
end

#pageObject (readonly)

Returns the value of attribute page.



16
17
18
# File 'lib/simple/sql/scope.rb', line 16

def page
  @page
end

#perObject (readonly)

Returns the value of attribute per.



16
17
18
# File 'lib/simple/sql/scope.rb', line 16

def per
  @per
end

Instance Method Details

#order_by(sql_fragment) ⇒ Object



84
85
86
# File 'lib/simple/sql/scope.rb', line 84

def order_by(sql_fragment)
  duplicate.order_by!(sql_fragment)
end

#order_by!(sql_fragment) ⇒ Object

Adjust sort order



79
80
81
82
# File 'lib/simple/sql/scope.rb', line 79

def order_by!(sql_fragment)
  @order_by_fragment = sql_fragment
  self
end

#paginate(per:, page:) ⇒ Object

Set pagination



67
68
69
# File 'lib/simple/sql/scope.rb', line 67

def paginate(per:, page:)
  duplicate.send(:paginate!, per: per, page: page)
end

#paginate!(per:, page:) ⇒ Object



71
72
73
74
75
76
# File 'lib/simple/sql/scope.rb', line 71

def paginate!(per:, page:)
  @per = per
  @page = page

  self
end

#paginated?Boolean

Is this a paginated scope?

Returns:

  • (Boolean)


91
92
93
# File 'lib/simple/sql/scope.rb', line 91

def paginated?
  not @per.nil?
end

#to_sql(pagination: :auto) ⇒ Object

generate a sql query

Raises:

  • (ArgumentError)


96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/simple/sql/scope.rb', line 96

def to_sql(pagination: :auto)
  raise ArgumentError unless pagination == :auto || pagination == false

  sql = @sql
  active_filters = @filters.compact
  unless active_filters.empty?
    sql += " WHERE (" + active_filters.join(") AND (") + ")"
  end

  if order_by_fragment
    sql += " ORDER BY #{order_by_fragment}"
  end

  if pagination == :auto && @per && @page
    raise ArgumentError, "per must be > 0" unless @per > 0
    raise ArgumentError, "page must be > 0" unless @page > 0

    sql += " LIMIT #{@per} OFFSET #{(@page - 1) * @per}"
  end

  sql
end

#where(sql_fragment, arg = :__dummy__no__arg, placeholder: "?") ⇒ Object

scope = Scope.new(“SELECT * FROM tablename”) scope = scope.where(“id > ?”, 12)

The placeholder (usually a ‘?’) is being replaced with the numbered argument (since postgres is using $1, $2, etc.) If your SQL fragment uses ‘?’ as part of some fixed text you must use an alternative placeholder symbol.

TODO: Add support for hash arguments, i.e. scope = scope.where(title: “foobar”)



51
52
53
# File 'lib/simple/sql/scope.rb', line 51

def where(sql_fragment, arg = :__dummy__no__arg, placeholder: "?")
  duplicate.send(:where!, sql_fragment, arg, placeholder: placeholder)
end

#where!(sql_fragment, arg = :__dummy__no__arg, placeholder: "?") ⇒ Object



55
56
57
58
59
60
61
62
63
64
# File 'lib/simple/sql/scope.rb', line 55

def where!(sql_fragment, arg = :__dummy__no__arg, placeholder: "?")
  if arg == :__dummy__no__arg
    @filters << sql_fragment
  else
    @args << arg
    @filters << sql_fragment.gsub(placeholder, "$#{@args.length}")
  end

  self
end