Variables

When you call a generated method (originated by a template), you can pass a list of hashes of variables that will be interpolated into the templates.

Notice: We will use just one hash in the following examples, but you can actually pass a list of hashes that will be deep merged into one single hash (see Single Call Level).

For example:

my_search:
- query:
    term:
      color: <<the_color>>
MyClass.my_search :the_color => 'blue'

You know that you can also set a tag default (see Tags):

my_search:
- query:
    term:
      color: <<the_color= blue >>
MyClass.my_search

but you can also set a default for all the the_color tags in the source file, or for all the source files used by your class, or for all the requests of your app, etc. by setting them at different levels.

Variable Levels

Flex allows you to set interpolation variables at different levels, affecting different ranges of requests. They act as sort of cascading defaults, so you can minimize the code needed to set the right value, which is somehow similar to what you do with CSSs.

That is internally achieved by deep-merging all the Flex::Variables objects in the cascading hierarchy of levels, from the most general to the most specific. More specific variable levels override more general levels.

Here they are, from the most general to the most specific:

1. Configuration Level

Variables set at configuration level will set the default for all the requests of your application and can be overridden by all the other levels. You usually set them by merging or deep-merging your values into the Flex::Variables object contained in Flex::Configuration.variables so preserving the values already there:

config.variables.deep_merge! :the_color => 'green'

(see Configuration)

2. Template Class level

This is mostly used internally by the Flex::Template::* subclasses. You might need it if you want to create a custom template class. In that case take a look at the implementation of flex/template/slim_search.

class MyTemplateClass < Flex::Template
  def self.variables
    super.deep_merge(:the_color => 'blue')
  end
  ...
end

3. Host Class level (your class)

When you want to set a default variable for all the requests from your own class (context class) you can simply add the variables to the flex class proxy of your class:

class MyClass
  include Flex::Templates
  flex.variables.deep_merge!(:the_color => 'red')
  flex.load_source :my_source
  ...
end

4. Source Level

When you want to set a default variable for all the requests generated by the same source file you can do so in the loading statement:

flex.load_source :my_source, :the_color => 'black'

(see Template Sources)

5. Instance Template Level

This level is specially useful when you want to set a variable at the template level (i.e. affecting all the requests made with that template), but you cannot use tag defaults because that tag is not explicit in your template. This is usually the case of the tags used in the path, such as :index, :type or (query) :params that are not accessible from Search Templates. In the following template, the second argument is used as template variables. In this case we want to use the car and truck default types when we use that template.

my_search:
- query:
    term:
      color: <<the_color>>
- type:
  - car
  - truck

6. Tag Level

This is a quite specific level: may be overridden only by the call argument below.

- <<the_color= yellow >>

7. Single Call Level

This is the most specific level where you can set a variable, indeed it affects only that single request and overrides any other level that may set :the_color.

MyClass.my_search :the_color => 'white'

Besides, all the methods that accept a variable hash, can accept a list of hashes as well. The list will be deep-merged and the resulting hash will be used as the final variable hash passed as the arguments. For example:

MyClass.my_search @default_controller_vars, params, :the_color => 'pink'

The order is important: in this case we pass 3 hashes: the 3rd hash will override the 2nd, which will override the 1st.

Special Variables

Variables are usually created by you: their primary function is supplying the values to replace the tags, but there are a few variables that are special because they have a different function, so you cannot define a tag with their name. They are mostly set and used internally, but you might need to pass it explicitly in some special case.

:context

This variable contain the context class, which is usually the class where you included some Flex module (like Flex::Templates, Flex::Scopes, Flex::ModelIndexer, etc.). It is used by the flex-scopes gem.

:path

This variable contain the full path of the request. It is usually set and used internally.

:data

This variable contain the data, i.e. the request body (a ruby structure that express the elasticsearch JSON query). You may need to set it directly in some very special case, but it is mostly used internally.

:params

The params are a hash of key/value pairs. Flex will transform them in the query string part of the path (all what comes after the ?), so you will probably use it quite often.

:no_pruning

Skips the automatic pruning for the keys listed here. You can skip arbitrary keys that are expected to containing nil/empty values (see Pruning)

:raise

Boolean. false will not raise errors coming from elasticsearch.

:raw_result

Boolean. true will return the raw result as returned by elasticsearch. It is mostly useful to skip the automatic casting provided by the Flex::ActiveModel module, or skip your own post processing of the result (see flex_result).

Predefined Variables

Flex defines a few tags internally, so it adds some predefined variable to the set. For example, when you use Search Templates, you have more predefined variables:

:index

The index or indices. You can set it as a string or as an Array of strings.

:type

The type or types. You can set it as a string or as an Array of strings.

:page

The page number of the pagination. By setting this variable you get automatically set the :from param, consistently with the :size (that is usually defaulted). Very convenient when you get the page number from a pagination link). Default 1.

:cleanable_query

This variable is used to pass query_string queries and it is treated in a special way by Flex. For example: if you pass a search field content from a web form directly to a query_string query, you may easily get some nasty error by elasticsearch. Indeed there are a few special characters that can break the Lucene syntax, so they should either be escaped/removed or used in a proper way. If you pass the query_string as the :cleanable_query variable, Flex tries to search with its content as is first (so allowing your power users to use advanced queries). But if it gets an error from elasticsearch, then it removes the offending characters from the string, and performs a second search with the cleaned string, and finally returns the result.

See Lucene Query Parser Syntax

my_template:
  query:
    query_string:
      query: <<cleanable_query= '*' >>

# or
my_other_template:
  query:
    query_string:
      # must wrap in quotes or the ':' would generate a YAML error
      "<<cleanable_query= {query: '*'} >>"

MyClass.my_template(:cleanable_query => params[:q])
MyClass.my_other_template( :cleanable_query => { :query  => params[:q],
                                                 :fields => ['text', 'category'] } )

When you use other API methods (e.g. Flex.multi_get, Flex.stats, …), you may need to set other variables as well (see API Methods). As usual you can get the variables and an usage example in the console with Flex.doc

Flex Variables Structure

When you pass a variable hash (or list of hashes) to any flex method, flex will create an internal Flex::Variables instance, which is a special Hash instance.