Class: Appfuel::Repository::Criteria

Inherits:
Object
  • Object
show all
Includes:
Domain::DomainNameParser
Defined in:
lib/appfuel/storage/repository/criteria.rb

Overview

The Criteria represents the interface between the repositories and actions or commands. The allow you to find entities in the application storage ( a database) without knowledge of that storage system. The criteria will always refer to its queries in the domain language for which the repo is responsible for mapping that query to its persistence layer.

global.user memberships.user

exist: ‘foo.bar exists id = 6’ search: ‘foo.bar filter id = 6 and bar = “foo” order id asc limit 6’

search:

domain: 'foo.bar',

filters: 'id = 6 or id = 8 and id = 9'
filters: [
  ['id', 'eq', '6', 'or']
]
filters: [
  {attr: 'id', op: 'eq', value: 999, or: true},
]

order: 'foo.bar.id asc'
order: 'foo.bar.id'
order: [
  'foo.bar.id',
  {desc: 'foo.bar.id'},
  {asc: 'foo.bar.id'}
]
limit: 1

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Domain::DomainNameParser

#parse_domain_attr, #parse_domain_name

Constructor Details

#initialize(domain_name, data = {}) ⇒ Criteria

Parse out the domain into feature, domain, determine the name of the repo this criteria is for and initailize basic settings. global.user

membership.user foo.id filter name like “foo” order foo.bar.id asc limit 2 foo.id exists foo.id = 5

Options

error_on_empty:   will cause the repo to fail when query returns an
                  an empty dataset. The failure will have the message
                  with key as domain and text is "<domain> not found"

single:           will cause the repo to return only one, the first,
                  entity in the dataset

Examples:

SpCore::Domain::Criteria('foo', single: true)
Types.Criteria('foo.bar', single: true)

Parameters:

  • domain (String)

    fully qualified domain name

  • opts (Hash)

    options for initializing criteria



106
107
108
109
110
111
112
113
114
115
# File 'lib/appfuel/storage/repository/criteria.rb', line 106

def initialize(domain_name, data = {})
  @feature, @domain_basename, @domain_name = parse_domain_name(domain_name)
  @filters   = nil
  @params    = {}
  @parser    = data[:expr_parser]    || ExprParser.new
  @transform = data[:expr_transform] || ExprTransform.new
  @limit     = nil
  @order_by  = []
  filter(data[:filters]) if data[:filters]
end

Instance Attribute Details

#domain_basenameObject (readonly)

Returns the value of attribute domain_basename.



38
39
40
# File 'lib/appfuel/storage/repository/criteria.rb', line 38

def domain_basename
  @domain_basename
end

#domain_nameObject (readonly)

Returns the value of attribute domain_name.



38
39
40
# File 'lib/appfuel/storage/repository/criteria.rb', line 38

def domain_name
  @domain_name
end

#featureObject (readonly)

Returns the value of attribute feature.



38
39
40
# File 'lib/appfuel/storage/repository/criteria.rb', line 38

def feature
  @feature
end

#filtersObject (readonly)

Returns the value of attribute filters.



38
39
40
# File 'lib/appfuel/storage/repository/criteria.rb', line 38

def filters
  @filters
end

#order_byObject (readonly)

Returns the value of attribute order_by.



38
39
40
# File 'lib/appfuel/storage/repository/criteria.rb', line 38

def order_by
  @order_by
end

Class Method Details

.build(inputs) ⇒ Object

1) Inputs form the SearchTransform.apply

search:
   domain:   [String],
   filters:  [Expr|ExprConjunction]
   orders:   [OrderExpr|Array[OrderExpr]]
   limit:    [Integer]

2) Inputs manually built from a developer

search:
  domain:   [String],
  filters:  [String|Array[String|Hash]]
  orders:   [String|Array[String|Hash]]
  limit:    [Integer]

3) Inputs as a full search string

search: [String]

domain: String, filters: String | Expr | ExprConjunction order: String | Array limit: Integer



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/appfuel/storage/repository/criteria.rb', line 66

def self.build(inputs)
  unless inputs.key?(:domain)
    fail "search criteria :domain is required"
  end
  criteria = self.new(inputs[:domain])
  criteria.filter(inputs[:filters])

  if inputs.key?(:order)
    criteria.order(inputs[:order])
  end

  if inputs.key?(:limit)
    criteria.limit(inputs[:limit])
  end
  criteria
end

Instance Method Details

#add_param(key, value) ⇒ String, Integer

Returns The saved value.

Examples:

criteria.add_param('foo', 100)

Parameters:

  • key (Symbol, String)

    The key name where we want to keep the value

  • value (String, Integer)

    The value that belongs to the key param

Returns:

  • (String, Integer)

    The saved value



139
140
141
142
143
# File 'lib/appfuel/storage/repository/criteria.rb', line 139

def add_param(key, value)
  fail 'key should not be nil' if key.nil?

  @params[key.to_sym] = value
end

#clear_filtersObject



117
118
119
# File 'lib/appfuel/storage/repository/criteria.rb', line 117

def clear_filters
  @filters = nil
end

#feature?Boolean

Returns:

  • (Boolean)


129
130
131
# File 'lib/appfuel/storage/repository/criteria.rb', line 129

def feature?
  @feature != 'global'
end

#filter(item, op: 'and') ⇒ Object



211
212
213
214
215
216
217
218
219
220
221
222
223
# File 'lib/appfuel/storage/repository/criteria.rb', line 211

def filter(item, op: 'and')
  case
  when item.is_a?(Array)  then filter_array(item)
  when item.is_a?(Hash)   then filter_hash(item)
  when item.is_a?(String) then filter_string(item, op: op)
  when item.instance_of?(expr_class),
       item.instance_of?(expr_conjunction_class)
    filter_expr(item, op: op)
  else
    fail "filter could not understand input (#{input})"
  end
  self
end

#filter_array(input) ⇒ Object

[

'id = 6',
{'name like "foo"' => 'or'},

]



168
169
170
171
172
173
174
175
176
# File 'lib/appfuel/storage/repository/criteria.rb', line 168

def filter_array(input)
  unless input.respond_to?(:each)
    fail "input must implement :each, expecting a list"
  end

  input.each do |item|
    filter(item)
  end
end

#filter_expr(expr, op: 'and') ⇒ Object



202
203
204
205
206
207
208
209
# File 'lib/appfuel/storage/repository/criteria.rb', line 202

def filter_expr(expr, op: 'and')
  expr = qualify_expr(expr)
  if filters?
    expr = expr_conjunction_class.new(op, filters, expr)
  end
  @filters = expr
  self
end

#filter_hash(input) ⇒ Object

filters:

'id = 6' => :and,
'id = 8' => :and,



190
191
192
193
194
195
196
197
198
199
200
# File 'lib/appfuel/storage/repository/criteria.rb', line 190

def filter_hash(input)
  unless input.respond_to?(:each)
    fail "input must implement :each, expecting a hash"
  end

  input.each do |expr, op|
    filter_string(expr, op: op)
  end

  self
end

#filter_string(expr, op: 'and') ⇒ Object



178
179
180
181
182
183
# File 'lib/appfuel/storage/repository/criteria.rb', line 178

def filter_string(expr, op: 'and')
  expr = parse_expr(expr)
  fail "Could not parse (#{expr}) unkown failure" unless expr
  filter_expr(expr, op: op)
  self
end

#filters?Boolean

Returns:

  • (Boolean)


121
122
123
# File 'lib/appfuel/storage/repository/criteria.rb', line 121

def filters?
  !filters.nil?
end

#global?Boolean

Returns:

  • (Boolean)


125
126
127
# File 'lib/appfuel/storage/repository/criteria.rb', line 125

def global?
  !feature?
end

#limit(nbr = nil) ⇒ Object



229
230
231
232
233
234
235
# File 'lib/appfuel/storage/repository/criteria.rb', line 229

def limit(nbr = nil)
  return @limit if nbr.nil?

  @limit = Integer(nbr)
  fail "limit must be an integer greater than 0" unless nbr > 0
  self
end

#limit?Boolean

Returns:

  • (Boolean)


225
226
227
# File 'lib/appfuel/storage/repository/criteria.rb', line 225

def limit?
  !@limit.nil?
end

#order(data) ⇒ Object

order first_name asc, last_name

order: 'foo.bar.id asc'
order: 'foo.bar.id'
order: [
  'foo.bar.id',
  'foo.bar.id asc',
  {'foo.bar.id => 'desc'},
  {'foo.bar.code => 'asc'},
]

membership.user.id



252
253
254
# File 'lib/appfuel/storage/repository/criteria.rb', line 252

def order(data)
 order_exprs(OrderExpr.build(data))
end

#order?Boolean

Returns:

  • (Boolean)


237
238
239
# File 'lib/appfuel/storage/repository/criteria.rb', line 237

def order?
  !@order_by.empty?
end

#order_expr(expr) ⇒ Object



256
257
258
259
# File 'lib/appfuel/storage/repository/criteria.rb', line 256

def order_expr(expr)
  @order_by << qualify_expr(expr)
  self
end

#order_exprs(list) ⇒ Object



261
262
263
264
265
266
# File 'lib/appfuel/storage/repository/criteria.rb', line 261

def order_exprs(list)
  list.each do |expr|
    order_expr(expr)
  end
  self
end

#param(key) ⇒ String, ...

Returns the found value.

Parameters:

  • key (String, Symbol)

Returns:

  • (String, Integer, Boolean)

    the found value



147
148
149
# File 'lib/appfuel/storage/repository/criteria.rb', line 147

def param(key)
  @params[key.to_sym]
end

#param?(key) ⇒ Boolean

Parameters:

  • key (String, Symbol)

Returns:

  • (Boolean)


153
154
155
# File 'lib/appfuel/storage/repository/criteria.rb', line 153

def param?(key)
  @params.key?(key.to_sym)
end

#params?Boolean

Returns if the @params variable has values.

Returns:

  • (Boolean)

    if the @params variable has values



158
159
160
# File 'lib/appfuel/storage/repository/criteria.rb', line 158

def params?
  !@params.empty?
end