Module: Zena::Use::QueryBuilder::ZafuMethods

Includes:
RubyLess
Defined in:
lib/zena/use/query_builder.rb

Overview

  1. try Zafu

<r:images in='site'>
  1. r_unknown

try RubyLess.translate(node, xxxxxx) <-- pass context
  1. helper (view) tries to resolve safe_method_type as RubyLess or PseudoSQL

Defined Under Namespace

Classes: DynamicQuery

Constant Summary collapse

QB_KEYS =
[:find, :from, :else, :in, :where, :or, :limit, :order]

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.included(base) ⇒ Object



148
149
150
# File 'lib/zena/use/query_builder.rb', line 148

def self.included(base)
  base.process_unknown :querybuilder_eval
end

Instance Method Details

#get_find_type(signature) ⇒ Object



134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/zena/use/query_builder.rb', line 134

def get_find_type(signature)
  if signature == ['find', Number]
    {:method => :find_node_by_zip, :class => VirtualClass['Node'], :nil => true, :accept_nil => true}
  elsif signature == ['find', String]
    # TODO: support dynamic strings ?
    {:method => 'nil', :pre_processor => :get_type_for_find,  :class => NilClass}
  elsif signature == ['count', String]
    # TODO: support dynamic strings ?
    {:method => '0',   :pre_processor => :get_type_for_count, :class => Number  }
  else
    nil
  end
end

#get_type_for_count(string) ⇒ Object

Pre-processing of the ‘count(“…”)’ method.



221
222
223
224
# File 'lib/zena/use/query_builder.rb', line 221

def get_type_for_count(string)
  finder = build_finder(:count, string, {})
  TypedString.new(finder.delete(:method), finder)
end

#get_type_for_find(string) ⇒ Object

Pre-processing of the ‘find(“…”)’ method.



212
213
214
215
216
217
218
# File 'lib/zena/use/query_builder.rb', line 212

def get_type_for_find(string)
  finder = build_finder(get_count(string, {}), string, {})
  TypedString.new(finder.delete(:method), finder)
rescue ::QueryBuilder::Error => err
  out parser_error(err.message)
  nil
end

#node_context_vars(finder) ⇒ Object

This method is called when we enter a new node context



257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
# File 'lib/zena/use/query_builder.rb', line 257

def node_context_vars(finder)
  sub_context = super
  query = finder[:query]
  if query && ((pagination_key = query.pagination_key) || child['count'])
    node_count = get_var_name('paginate', 'nodes', sub_context)
    set_context_var('set_var', 'count', RubyLess::TypedString.new(node_count, Number))

    res = "#{node_count} = Node.do_find(:count, #{query.to_s(:count)})"
    if pagination_key
      # Full pagination needed
      set_context_var('paginate', 'key', pagination_key, sub_context)

      page_count = get_var_name('paginate', 'count', sub_context)
      curr_page  = get_var_name('paginate', 'current', sub_context)

      # Give access to the page number through the pagination key.
      set_context_var('set_var', pagination_key, RubyLess::TypedString.new(curr_page, Number))
      # Give access to page_count and count
      # FIXME: DOC
      set_context_var('set_var', 'page_count', RubyLess::TypedString.new(page_count, Number))

      res << "; #{page_count} = (#{node_count} / #{query.page_size.to_f}).ceil; #{curr_page} = [1,params[:#{pagination_key}].to_i].max"
    end

    out "<% #{res} %>"

  elsif finder[:method].kind_of?(RubyLess::TypedString)
    # Hash passed with :zafu => {} is inserted into context
    sub_context.merge!(finder[:method].opts[:zafu] || {})
  end

  sub_context[:has_link_id] = query && query.select_keys.include?('link_id')

  sub_context
end

#querybuilder_eval(method = @method) ⇒ Object

Resolve unknown methods by trying to build a pseudo-sql query with QueryBuilder.



227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
# File 'lib/zena/use/query_builder.rb', line 227

def querybuilder_eval(method = @method)
  node = single_node

  if method =~ /^\d+$/
    finder = {:method => "find_node_by_zip(#{method})", :class => VirtualClass['Node'], :nil => true}
  else
    count  = get_count(method, @params)
    finder = build_finder(count, method, @params)
  end

  if count == :count && @blocks.empty?
    out "<%= #{finder[:method]} %>"
  else
    expand_with_finder(finder)
  end
rescue ::QueryBuilder::Error => err
  parser_continue(err.message)
end

#r_queryObject

Open a list context with a query comming from the url params. Default param name is “qb”



176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
# File 'lib/zena/use/query_builder.rb', line 176

def r_query
  return parser_error("Cannot be used in list context (#{node.class_name})") if node.list_context?
  return parser_error("Missing 'default' query") unless default_psql = @params[:default]

  begin
    default = build_finder(:all, default_psql, {})
    default_query = default[:query]
  rescue ::QueryBuilder::Error => err
    return parser_error(err.message)
  end

  klass = [default_query.main_class]

  can_be_nil = true
  if sql = @params[:eval]
    sql = RubyLess.translate(self, sql)
    unless sql.klass <= String
      return parser_error("Invalid compilation result for #{sql.inspect} (#{sql.klass})")
    end
    can_be_nil = sql.opts[:nil]
  elsif sql = @params[:select]
    sql = RubyLess.translate_string(self, sql)
    can_be_nil = sql.opts[:nil]
  else
    sql = "params[:qb]"
  end

  if can_be_nil
    sql = "#{sql} || #{default_psql.inspect}"
  end

  query = DynamicQuery.new(default_query, node, sql)
  expand_with_finder(:method => query.to_s, :class => [query.main_class], :nil => true, :query => query)
end

#show_errorsObject

Select the most pertinent error between RubyLess processing errors and QueryBuilder errors.



247
248
249
250
251
252
253
254
# File 'lib/zena/use/query_builder.rb', line 247

def show_errors
  if @method =~ / in | where | from / || (QB_KEYS & @params.keys != [])
    # probably a query
    @errors.detect {|e| e =~ /Syntax/} || @errors.last
  else
    @errors.first
  end
end