Class: ROM::SQL::Attribute

Inherits:
ROM::Schema::Attribute
  • Object
show all
Defined in:
lib/rom/sql/attribute.rb

Overview

Extended schema attributes tailored for SQL databases

Constant Summary collapse

QualifyError =

Error raised when an attribute cannot be qualified

Class.new(StandardError)

Instance Method Summary collapse

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(meth, *args, &block) ⇒ Object (private)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Delegate to sql expression if it responds to a given method



239
240
241
242
243
244
245
# File 'lib/rom/sql/attribute.rb', line 239

def method_missing(meth, *args, &block)
  if sql_expr.respond_to?(meth)
    meta(sql_expr: sql_expr.__send__(meth, *args, &block))
  else
    super
  end
end

Instance Method Details

#aliased(name) ⇒ SQL::Attribute Also known as: as

Return a new attribute with an alias

Examples:

users[:id].aliased(:user_id)


23
24
25
# File 'lib/rom/sql/attribute.rb', line 23

def aliased(name)
  super.meta(name: meta.fetch(:name, name), sql_expr: sql_expr.as(name))
end

#canonicalObject

Return a new attribute in its canonical form



31
32
33
34
35
36
37
# File 'lib/rom/sql/attribute.rb', line 31

def canonical
  if aliased?
    meta(alias: nil, sql_expr: nil)
  else
    self
  end
end

#concat(other, sep = ' ') ⇒ SQL::Function

Create a CONCAT function from the attribute

Examples:

with default separator (‘ ’)

users[:id].concat(users[:name])

with custom separator

users[:id].concat(users[:name], '-')


210
211
212
# File 'lib/rom/sql/attribute.rb', line 210

def concat(other, sep = ' ')
  Function.new(type).concat(self, sep, other)
end

#foreign_keySQL::Attribute

Return a new attribute marked as a FK



106
107
108
# File 'lib/rom/sql/attribute.rb', line 106

def foreign_key
  meta(foreign_key: true)
end

#func(&block) ⇒ SQL::Function

Create a function DSL from the attribute

Examples:

users[:id].func { int::count(id).as(:count) }


193
194
195
# File 'lib/rom/sql/attribute.rb', line 193

def func(&block)
  ProjectionDSL.new(name => self).call(&block).first
end

#in(*args) ⇒ Object

Return a boolean expression with an inclusion test

If the single argument passed to the method is a Range object then the resulting expression will restrict the attribute value with range’s bounds. Upper bound condition will be inclusive/non-inclusive depending on the range type.

If more than one argument is passed to the method or the first argument is not Range then the result will be a simple IN check.

Examples:

users.where { id.in(1..100) | created_at(((Time.now - 86400)..Time.now)) }
users.where { id.in(1, 2, 3) }
users.where(users[:id].in(1, 2, 3))


173
174
175
176
177
178
179
180
181
182
183
# File 'lib/rom/sql/attribute.rb', line 173

def in(*args)
  if args.first.is_a?(Range)
    range = args.first
    lower_cond = __cmp__(:>=, range.begin)
    upper_cond = __cmp__(range.exclude_end? ? :< : :<=, range.end)

    Sequel::SQL::BooleanExpression.new(:AND, lower_cond, upper_cond)
  else
    __cmp__(:IN, args)
  end
end

#is(other) ⇒ Object

Return a boolean expression with ‘=` operator

Examples:

users.where { id.is(1) }

users.where(users[:id].is(1))


151
152
153
# File 'lib/rom/sql/attribute.rb', line 151

def is(other)
  __cmp__(:'=', other)
end

#joinedSQL::Attribute

Return a new attribute marked as joined

Whenever you join two schemas, the right schema’s attribute will be marked as joined using this method



67
68
69
# File 'lib/rom/sql/attribute.rb', line 67

def joined
  meta(joined: true)
end

#joined?Boolean

Return if an attribute was used in a join

Examples:

schema = users.schema.join(tasks.schema)

schema[:id, :tasks].joined?
# => true


82
83
84
# File 'lib/rom/sql/attribute.rb', line 82

def joined?
  meta[:joined].equal?(true)
end

#qualifiedSQL::Attribute

Return a new attribute marked as qualified

Examples:

users[:id].aliased(:user_id)


47
48
49
50
51
52
53
54
55
56
57
# File 'lib/rom/sql/attribute.rb', line 47

def qualified
  return self if qualified?

  case sql_expr
  when Sequel::SQL::AliasedExpression, Sequel::SQL::Identifier
    type = meta(qualified: true)
    type.meta(qualified: true, sql_expr: Sequel[type.to_sym])
  else
    raise QualifyError, "can't qualify #{name.inspect} (#{sql_expr.inspect})"
  end
end

#qualified?Boolean

Return if an attribute type is qualified

Examples:

id = users[:id].qualify

id.qualified?
# => true


97
98
99
# File 'lib/rom/sql/attribute.rb', line 97

def qualified?
  meta[:qualified].equal?(true)
end

#sql_literal(ds) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Sequel calls this method to coerce an attribute into SQL string



219
220
221
222
223
224
225
# File 'lib/rom/sql/attribute.rb', line 219

def sql_literal(ds)
  if sql_expr
    sql_expr.sql_literal(ds)
  else
    Sequel[to_sym].sql_literal(ds)
  end
end

#to_symSymbol

Return symbol representation of an attribute

This uses convention from sequel where double underscore in the name is used for qualifying, and triple underscore means aliasing

Examples:

users[:id].qualified.to_sym
# => :users__id

users[:id].as(:user_id).to_sym
# => :id___user_id

users[:id].qualified.as(:user_id).to_sym
# => :users__id___user_id


128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/rom/sql/attribute.rb', line 128

def to_sym
  @_to_sym ||=
    if qualified? && aliased?
      :"#{source.dataset}__#{name}___#{meta[:alias]}"
    elsif qualified?
      :"#{source.dataset}__#{name}"
    elsif aliased?
      :"#{name}___#{meta[:alias]}"
    else
      name
    end
end