Class: SpCore::Domain::CriteriaBuilder

Inherits:
Object
  • Object
show all
Defined in:
lib/appfuel/domain/criteria_builder.rb

Overview

CriteriaBuilder is an interface creating new Criteria as well as building up an existing Criteria instance

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(inputs, maps) ⇒ Criteria

Builds new Criteria object

Parameters:

  • inputs (Hash)

    input data

  • maps (Hash)

    mapping data

Options Hash (inputs):

  • :search (String)

    entity/domain to search for

  • :repo_map (Hash)

    repository mapping by entity/domain

  • :filters (Array)

    list of filter items

  • :order (Array)

    list of order definitions

  • :limit (Integer)

    number of records to limit to

  • :all (Boolean)

    flag for returning all records

  • :first (Boolean)

    flag for returning only first record

  • :last (Boolean)

    flag for returning only last record

  • :page (Integer)

    number of the page in collection

  • :per_page (Integer)

    num. of items per page in collection

  • :single_page (Boolean)

    flag for getting single page only

Options Hash (maps):

  • :attr_map (Hash)

    mapping by attr to domain.attribute_name



64
65
66
67
68
69
70
71
72
# File 'lib/appfuel/domain/criteria_builder.rb', line 64

def initialize(inputs, maps)
  domain_name   =  inputs.fetch(:search).to_s
  repo_map =       inputs[:repo_map] || {}
  fail ":repo_map must be a Hash" unless repo_map.is_a?(Hash)

  @attr_map =      maps[:attr_map] || {}
  @domain_name   =      "#{domain_name}"
  @repo_name = repo(repo_map, domain_name)
end

Class Method Details

.build(inputs, maps = {}) ⇒ Criteria

For the list of defined inputs and maps, it builds new Criteria object following build pattern

Examples:


inputs = {
  search: "projects.offer",
  repo_map: { "projects.offer" => "foo" },
  filters: [
    {foo: 'bar', ep: 1}
  ],
  order: [
    {created_at: :desc}
  ],
  limit: 5,
  all: true,
  page: 1,
  per_page: 10
}

maps = {
  feature: "projects",
  attr_map: {
    foo: "users.user.foo"
  }
}

criteria_builder = SpCore::Domain::CriteriaBuilder.build(inputs, maps)

Parameters:

  • inputs (Hash)

    input data

  • maps (Hash) (defaults to: {})

    mapping data

Returns:

  • (Criteria)


40
41
42
43
44
45
# File 'lib/appfuel/domain/criteria_builder.rb', line 40

def self.build(inputs, maps = {})
  builder = new(inputs, maps)
  criteria = builder.create
  builder.build(criteria, inputs)
  criteria
end

Instance Method Details

#build(criteria, inputs) ⇒ Object

Build criteria clauses

Parameters:

  • inputs (Hash)


87
88
89
90
91
92
93
# File 'lib/appfuel/domain/criteria_builder.rb', line 87

def build(criteria, inputs)
  self.filters(criteria, inputs, attr_map)
      .order(criteria, inputs, attr_map)
      .limit(criteria, inputs)
      .scope(criteria, inputs)
      .pagination(criteria, inputs)
end

#createCriteria

Creates new Criteria instance. Actually it’s just a delegator to Criteria initializer

Parameters:

  • domain (String)

    fully qualified domain name

  • options (Hash)

    options for initializing Criteria

Returns:

  • (Criteria)


80
81
82
# File 'lib/appfuel/domain/criteria_builder.rb', line 80

def create
  Criteria.new(domain_name, repo: repo_name)
end

#filters(criteria, inputs, attr_map = {}) ⇒ CriteriaBuilder

Updates Criteria object filters with the list of given filters Each filter item must be a Hash.

Examples:

inputs = {
  filters: [
    {first_name: 'Bob'},
    {last_name: 'Doe', op: 'like'},
    {last_name: 'Johnson', op: 'like', or: false}
  ]
}

Parameters:

  • criteria (Criteria)

    criteria object to build

  • inputs (Hash)

    input data

  • attr_map (Hash) (defaults to: {})

    mapping by attr to domain.attribute_name

Options Hash (inputs):

  • :filters (Array)

    list of filter items

Returns:



112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/appfuel/domain/criteria_builder.rb', line 112

def filters(criteria, inputs, attr_map = {})
  if inputs.key?(:filters)
    filters = inputs.fetch(:filters)
    fail ":filters must be an Array" unless filters.is_a?(Array)

    filters.each do |filter_item|
      attr_name, value = filter_item.first
      qualified_name = lookup_attribute(attr_name, attr_map)
      if qualified_name != attr_name
        filter_item.delete(attr_name)
        filter_item[qualified_name] = value
      end
    end

    criteria.filter(filters)
  end
  self
end

#limit(criteria, inputs) ⇒ CriteriaBuilder

Updates given Criteria record limit

Parameters:

  • criteria (Criteria)

    criteria to build

  • inputs (Hash)

    input data

Options Hash (inputs):

  • :limit (Integer)

    number of records to limit to

Returns:



179
180
181
182
183
184
# File 'lib/appfuel/domain/criteria_builder.rb', line 179

def limit(criteria, inputs)
  if inputs.key?(:limit)
    criteria.limit(inputs.fetch(:limit))
  end
  self
end

#order(criteria, inputs, attr_map = {}) ⇒ CriteriaBuilder

Updates given Criteria ordering clause. It expects a list of order definitions. Order definition might be either Hash, String or Symbol. If item is String or Symbol, ordering direction is ascending(:asc)

Examples:

inputs = {
  order: [
    {created_at: :desc},
    'created_at',
    :created_at
  ]
}

Parameters:

  • criteria (Criteria)

    criteria object to build

  • inputs (Hash)

    input data

  • attr_map (Hash) (defaults to: {})

    mapping by attr to domain.attribute_name

Options Hash (inputs):

  • :order (Array)

    list of order definitions

Returns:



150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/appfuel/domain/criteria_builder.rb', line 150

def order(criteria, inputs, attr_map = {})
  return self unless inputs.key?(:order)
  list = inputs.fetch(:order)

  fail ":order must implement :each" unless list.respond_to?(:each)
  return self if list.empty?

  final_order = {}
  list.each do |order|
    domain_attr_name = order
    order_dir = "asc"

    if order.is_a?(Hash)
      domain_attr_name, order_dir = order.first
    end

    qualified_name = lookup_attribute(domain_attr_name, attr_map)
    final_order[qualified_name.to_s] = order_dir.to_s
    criteria.order_by(final_order)
  end
  self
end

#pagination(criteria, inputs) ⇒ CriteriaBuilder

Updates given Criteria pagination params.

Parameters:

  • criteria (Criteria)

    criteria to build

  • inputs (Hash)

    input data

  • attr_map (Hash)

    mapping by attr to domain.attribute_name

Options Hash (inputs):

  • :page (Integer)

    number of the page within collection

  • :per_page (Integer)

    number of items per page

  • :single_page (Boolean)

    flag for getting single page only

Returns:



217
218
219
220
221
222
# File 'lib/appfuel/domain/criteria_builder.rb', line 217

def pagination(criteria, inputs)
  criteria.disable_pagination           if inputs[:single_page]==true || inputs[:disable_pagination] == true
  criteria.page(inputs[:page])          if inputs[:page]
  criteria.per_page(inputs[:per_page])  if inputs[:per_page]
  self
end

#scope(criteria, inputs) ⇒ CriteriaBuilder

Updates given Criteria collection limits. Those are :disable_pagination, :all, :first and :last properties.

Parameters:

  • criteria (Criteria)

    criteria to build

  • inputs (Hash)

    input data

Options Hash (inputs):

  • :all (Boolean)

    flag for returning all records

  • :first (Boolean)

    flag for returning onnly first record

  • :last (Boolean)

    flag for returning only last record

Returns:



195
196
197
198
199
200
201
202
203
204
205
206
# File 'lib/appfuel/domain/criteria_builder.rb', line 195

def scope(criteria, inputs)
  if inputs[:first] == true
    criteria.first
  elsif inputs[:last] == true
    criteria.last
  elsif inputs[:disable_pagination] == true
    criteria.disable_pagination
  elsif inputs[:all] == true
    criteria.all
  end
  self
end