Class: AzaharaSchema::Schema

Inherits:
Object
  • Object
show all
Defined in:
lib/azahara_schema/schema.rb

Direct Known Subclasses

ModelSchema

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(model, **attributes) ⇒ Schema

Returns a new instance of Schema.



36
37
38
39
40
41
42
# File 'lib/azahara_schema/schema.rb', line 36

def initialize(model, **attributes)
  @model = model
  @association = attributes[:association]
  @parent_schema = attributes[:parent_schema]
  @column_names = attributes[:columns]
  @enabled_outputs = attributes[:outputs] || default_outputs
end

Instance Attribute Details

#associationObject

Returns the value of attribute association.



32
33
34
# File 'lib/azahara_schema/schema.rb', line 32

def association
  @association
end

#enabled_outputsObject

Returns the value of attribute enabled_outputs.



32
33
34
# File 'lib/azahara_schema/schema.rb', line 32

def enabled_outputs
  @enabled_outputs
end

#limitObject

Returns the value of attribute limit.



34
35
36
# File 'lib/azahara_schema/schema.rb', line 34

def limit
  @limit
end

#modelObject

Returns the value of attribute model.



32
33
34
# File 'lib/azahara_schema/schema.rb', line 32

def model
  @model
end

#offsetObject

Returns the value of attribute offset.



34
35
36
# File 'lib/azahara_schema/schema.rb', line 34

def offset
  @offset
end

#parent_schemaObject

Returns the value of attribute parent_schema.



32
33
34
# File 'lib/azahara_schema/schema.rb', line 32

def parent_schema
  @parent_schema
end

#search_queryObject

Returns the value of attribute search_query.



33
34
35
# File 'lib/azahara_schema/schema.rb', line 33

def search_query
  @search_query
end

Class Method Details

.enabled_filters(*filter_names) ⇒ Object



19
20
21
22
# File 'lib/azahara_schema/schema.rb', line 19

def self.enabled_filters(*filter_names)
  @enabled_filters = filter_names if filter_names.any?
  @enabled_filters ||= []
end

.filter_operators(filter, operators) ⇒ Object



28
29
30
# File 'lib/azahara_schema/schema.rb', line 28

def self.filter_operators(filter, operators)
  operators_for_filters[filter] = operators
end

.operators_for_filtersObject



24
25
26
# File 'lib/azahara_schema/schema.rb', line 24

def self.operators_for_filters
  @operators_for_filters ||= {}
end

.schema_for(klass, *attributes) ⇒ Object



6
7
8
9
10
11
12
13
14
15
16
17
# File 'lib/azahara_schema/schema.rb', line 6

def self.schema_for(klass, *attributes)
  klasses = [klass]
  while klass != klass.base_class
    klass = klass.superclass
    klasses << klass
  end
  klasses.each do |kls|
    schema_klass = "#{kls.name}Schema".safe_constantize
    return schema_klass.new(*attributes) if schema_klass
  end
  AzaharaSchema::Schema.new(klass, *attributes)
end

Instance Method Details

#add_filter(name, operator, values) ⇒ Object



104
105
106
107
# File 'lib/azahara_schema/schema.rb', line 104

def add_filter(name, operator, values)
  raise 'filter ('+name+') is not defined!' unless available_filters.key?(name)
  filters[name] = { o: operator, v: values }
end

#add_short_filter(name, str) ⇒ Object

ACCESSORS



94
95
96
97
98
99
100
101
102
# File 'lib/azahara_schema/schema.rb', line 94

def add_short_filter(name, str)
  attrs = str.split('|')
  if attrs.size == 2
    operator, values = attrs
  elsif attrs.size == 1
    operator, values = '=', attrs.first
  end
  add_filter(name, operator, values.split('\\'))
end

#add_sort(name, order = :asc) ⇒ Object



109
110
111
# File 'lib/azahara_schema/schema.rb', line 109

def add_sort(name, order=:asc)
  sort[name] = order
end

#as_json(options = {}) ⇒ Object



270
271
272
273
# File 'lib/azahara_schema/schema.rb', line 270

def as_json(options={})
  build_json_options!(options)
  entities.collect{|entity| entity_as_json(entity, options) }
end

#association_pathObject



166
167
168
# File 'lib/azahara_schema/schema.rb', line 166

def association_path
  @association_path ||= parent_schema ? ( parent_schema.association_path + [association.name] ) : [model.model_name.element.to_sym]
end

#attribute(name) ⇒ Object



127
128
129
# File 'lib/azahara_schema/schema.rb', line 127

def attribute(name)
  available_attributes.detect{|att| att.name == name}
end

#attribute_for_column(col) ⇒ Object



181
182
183
184
185
# File 'lib/azahara_schema/schema.rb', line 181

def attribute_for_column(col)
  t = 'list' if model.defined_enums[col.name]
  t ||= col.type
  Attribute.new(model, col.name, t)
end

#available_associationsObject



170
171
172
173
174
175
176
177
178
179
# File 'lib/azahara_schema/schema.rb', line 170

def available_associations
  @available_associations ||= model.reflect_on_all_associations.select do |association|
    !association.options[:polymorphic] &&
      association.klass != model &&
      !association_path.include?( association.name.to_s.singularize.to_sym ) &&
      !association_path.include?( association.name.to_s.pluralize.to_sym )
  end.collect do |association|
    AzaharaSchema::Schema.schema_for(association.klass, parent_schema: self, association: association)
  end
end

#available_attributesObject



131
132
133
134
135
136
137
# File 'lib/azahara_schema/schema.rb', line 131

def available_attributes
  unless @available_attributes
    initialize_available_attributes
    @available_attributes.each{|at| at.table_alias = Array(association_path[1..-1]).collect(&:to_s).join('_').presence }
  end
  @available_attributes
end

#available_attributes_hashObject



139
140
141
# File 'lib/azahara_schema/schema.rb', line 139

def available_attributes_hash
  available_attributes.inject({}){|obj, aa| obj[aa.name] = aa; obj }
end

#available_columnsObject



143
144
145
# File 'lib/azahara_schema/schema.rb', line 143

def available_columns
  @available_columns ||= available_attributes.select{|att| att.column? }
end

#available_filtersObject



162
163
164
# File 'lib/azahara_schema/schema.rb', line 162

def available_filters
  @available_filters ||= available_attributes_hash.slice(*enabled_filter_names)
end

#build_json_options!(options = {}) ⇒ Object



246
247
248
249
# File 'lib/azahara_schema/schema.rb', line 246

def build_json_options!(options={})
  columns.each{|col| col.build_json_options!(options) }
  options
end

#collapsable_filtersObject



320
321
322
# File 'lib/azahara_schema/schema.rb', line 320

def collapsable_filters
  available_filters
end

#column_namesObject



53
54
55
# File 'lib/azahara_schema/schema.rb', line 53

def column_names
  @column_names ||= default_columns
end

#column_names=(values) ⇒ Object



48
49
50
51
# File 'lib/azahara_schema/schema.rb', line 48

def column_names=(values)
  @column_names = values
  @columns = nil
end

#columnsObject



57
58
59
# File 'lib/azahara_schema/schema.rb', line 57

def columns
  @columns ||= available_attributes_hash.slice(*column_names).values
end

#default_columnsObject



75
76
77
# File 'lib/azahara_schema/schema.rb', line 75

def default_columns
  [main_attribute_name]
end

#default_outputsObject

DEFAULTS



71
72
73
# File 'lib/azahara_schema/schema.rb', line 71

def default_outputs
  [AzaharaSchema::Outputs.registered_outputs.keys.first].compact
end

#default_sortObject



79
80
81
# File 'lib/azahara_schema/schema.rb', line 79

def default_sort
  {}
end

#disabled_filtersObject



151
152
153
# File 'lib/azahara_schema/schema.rb', line 151

def disabled_filters
  []
end

#enabled_filter_namesObject



155
156
157
158
159
160
# File 'lib/azahara_schema/schema.rb', line 155

def enabled_filter_names
  names = self.class.enabled_filters if self.class.enabled_filters.any?
  names ||= available_attributes_hash.keys
  names &= enabled_filters if enabled_filters
  names -= disabled_filters
end

#enabled_filtersObject



147
148
149
# File 'lib/azahara_schema/schema.rb', line 147

def enabled_filters

end

#entitiesObject



232
233
234
235
236
237
238
239
240
241
242
243
244
# File 'lib/azahara_schema/schema.rb', line 232

def entities
  scope = filtered_scope
  columns.each do |col|
    scope = col.add_preload(scope)
  end
  sort.each do |name, order|
    att = attribute(name)
    scope = att.add_sort(scope, order) if att
  end
  scope = scope.offset(offset) if offset
  scope = scope.limit(limit) if limit
  scope
end

#entity_as_json(entity, options = nil) ⇒ Object



251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
# File 'lib/azahara_schema/schema.rb', line 251

def entity_as_json(entity, options=nil)
  attr_hash = entity.as_json(options)
  # TODO serializable_add_includes(options) do |association, records, opts|
  columns.each do |col|
    col_sub_hash = attr_hash
    sub_col = col
    while sub_col.is_a?(AzaharaSchema::AssociationAttribute)
      col_sub_hash = (col_sub_hash[sub_col.association.name.to_s] ||= {})
      sub_col = sub_col.attribute
    end
    if col.type == 'love'
      col_sub_hash[sub_col.name] = sub_col.available_values.detect{|l, v| v == col_sub_hash[sub_col.name] }.try(:[], 0)
    else
      col_sub_hash[sub_col.name] = col.value(entity)
    end
  end
  attr_hash
end

#entity_countObject



228
229
230
# File 'lib/azahara_schema/schema.rb', line 228

def entity_count
  filtered_scope.count
end

#entity_scopeObject



210
211
212
# File 'lib/azahara_schema/schema.rb', line 210

def entity_scope
  model.respond_to?(:visible) ? model.visible : model.all
end

#filtered_scopeObject



214
215
216
217
218
219
220
221
222
223
224
225
226
# File 'lib/azahara_schema/schema.rb', line 214

def filtered_scope
  scope = entity_scope
  filters.each do |name, attrs|
    scope = available_filters[name].add_statement(scope, attrs[:o], attrs[:v])
  end
  if (tokens = tokenize_search_query)
    searchable_attributes.each{|a| scope = a.add_join(scope) }
    arl = searchable_attributes[0].arel_statement('~', tokens) if searchable_attributes.any?
    Array(searchable_attributes[1..-1]).each{|att| arl = arl.or( att.arel_statement('~', tokens) ) }
    scope = scope.where(arl)
  end
  scope
end

#filtersObject



61
62
63
# File 'lib/azahara_schema/schema.rb', line 61

def filters
  @filters ||= {}
end

#follow_nested_relationsObject



88
89
90
# File 'lib/azahara_schema/schema.rb', line 88

def follow_nested_relations
  true
end

#from_params(params) ⇒ Object

serialization



277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
# File 'lib/azahara_schema/schema.rb', line 277

def from_params(params)
  if params[:f]
    filter_params = params[:f].permit(available_filters.keys + [available_filters.keys.inject({}){|o,name| o[name] = []; o }]).to_h
    filter_params.each do |name, filter_value|
      next if filter_value.blank?
      if filter_value.is_a?(Array)
        add_filter(name, '=', filter_value)
      else
        add_short_filter(name, filter_value)
      end
    end
  end
  if params[:c].is_a?(Array)
    self.column_names = params[:c].to_a
  end
  if params[:sort]
    @sort = nil
    params[:sort].each do |k, sort|
      add_sort(sort[:path], sort['desc'] == 'true' ? :desc : :asc )
    end
  end
  self.search_query = params[:q] if params[:q]
  self.offset = params[:offset] if params[:offset]
  self.limit = params[:limit] if params[:limit]
end

#initialize_available_attributesObject



187
188
189
190
191
192
193
194
195
196
197
198
199
200
# File 'lib/azahara_schema/schema.rb', line 187

def initialize_available_attributes
  @available_attributes ||= []
  model.columns.each do |col|
    @available_attributes << attribute_for_column(col)
  end
  available_associations.each do |asoc_schema|
    asoc_schema.available_attributes.each do |asoc_attribute|
      next if asoc_attribute.is_a?(AggregationAttribute)
      added_attribute = AssociationAttribute.new(model, asoc_schema, asoc_attribute)
      @available_attributes << added_attribute
      @available_attributes << AggregationAttribute.new(model, added_attribute) if asoc_attribute.aggregable?
    end
  end
end

#main_attribute_nameObject

just a dummy implementation



84
85
86
# File 'lib/azahara_schema/schema.rb', line 84

def main_attribute_name
  available_attributes.detect{|att| att.name != 'id' }.name
end

#operator_for(fname) ⇒ Object



113
114
115
# File 'lib/azahara_schema/schema.rb', line 113

def operator_for(fname)
  filters[fname] && filters[fname][:o]
end

#operators_for(filter_name) ⇒ Object



121
122
123
124
125
# File 'lib/azahara_schema/schema.rb', line 121

def operators_for(filter_name)
  operators = available_filters[filter_name] && available_filters[filter_name].available_operators
  operators &= self.class.operators_for_filters[filter_name] if operators && self.class.operators_for_filters[filter_name]
  operators
end

#outputsObject



202
203
204
# File 'lib/azahara_schema/schema.rb', line 202

def outputs
  Outputs.new(self)
end

#searchable_attributesObject



44
45
46
# File 'lib/azahara_schema/schema.rb', line 44

def searchable_attributes
  @searchable_attributes ||= available_attributes.select{|a| a.searchable? }
end

#sortObject



65
66
67
# File 'lib/azahara_schema/schema.rb', line 65

def sort
  @sort ||= default_sort
end

#to_paramObject



303
304
305
306
307
308
309
310
311
312
313
314
# File 'lib/azahara_schema/schema.rb', line 303

def to_param
  params = {}
  params[:f] = {}
  filters.each do |fname, attrs|
    params[:f][fname] = "#{attrs[:o]}|#{Array(attrs[:v]).collect{|v| v.to_s}.join('\\')}"
  end
  params[:c] = column_names
  params[:q] = search_query if params[:q]
  params[:offset] = offset
  params[:limit] = limit
  params
end

#tokenize_search_query(query = search_query) ⇒ Object



206
207
208
# File 'lib/azahara_schema/schema.rb', line 206

def tokenize_search_query(query=search_query)
  query.split if query
end

#uncollapsable_filtersObject



316
317
318
# File 'lib/azahara_schema/schema.rb', line 316

def uncollapsable_filters
  {}
end

#value_for(fname) ⇒ Object



117
118
119
# File 'lib/azahara_schema/schema.rb', line 117

def value_for(fname)
  filters[fname] && filters[fname][:v]
end