lib/scoped_search/definition.rb in scoped_search-4.1.5 vs lib/scoped_search/definition.rb in scoped_search-4.1.6

- old
+ new

@@ -15,11 +15,11 @@ # class, so you should not create instances of this class yourself. class Field attr_reader :definition, :field, :only_explicit, :relation, :key_relation, :full_text_search, :key_field, :complete_value, :complete_enabled, :offset, :word_size, :ext_method, :operators, - :validator + :validator, :value_translation, :special_values # Initializes a Field instance given the definition passed to the # scoped_search call on the ActiveRecord-based model class. # # Field name may be given in positional 'field' argument or 'on' named @@ -40,18 +40,22 @@ only_explicit: nil, operators: nil, profile: nil, relation: nil, rename: nil, + special_values: [], validator: nil, + value_translation: nil, word_size: 1, **kwargs) # Prefer 'on' kw arg if given, defaults to the 'field' positional to allow either syntax raise ArgumentError, "Missing field or 'on' keyword argument" if on.nil? @field = on.to_sym + raise ArgumentError, "'special_values' must be an Array" unless special_values.kind_of?(Array) + # Reserved Ruby keywords so access via kwargs instead, but deprecate them for future versions if kwargs.key?(:in) relation = kwargs.delete(:in) ActiveSupport::Deprecation.warn("'in' argument deprecated, prefer 'relation' since scoped_search 4.0.0", caller(6)) end @@ -75,12 +79,14 @@ @key_relation = in_key @offset = offset @only_explicit = !!only_explicit @operators = operators @relation = relation + @special_values = special_values @validator = validator @word_size = word_size + @value_translation = value_translation # Store this field in the field array definition.define_field(rename || @field, self) # Store definition for aliases as well @@ -152,10 +158,14 @@ # Returns true if this is a textual column. def textual? [:string, :text].include?(type) end + def uuid? + type == :uuid + end + # Returns true if this is a set. def set? complete_value.is_a?(Hash) end @@ -236,26 +246,28 @@ def operator_by_field_name(name) field = field_by_name(name) return [] if field.nil? return field.operators if field.operators return ['=', '!=', '>', '<', '<=', '>=', '~', '!~', '^', '!^'] if field.virtual? - return ['=', '!='] if field.set? + return ['=', '!='] if field.set? || field.uuid? return ['=', '>', '<', '<=', '>=', '!=', '^', '!^'] if field.numerical? return ['=', '!=', '~', '!~', '^', '!^'] if field.textual? return ['=', '>', '<'] if field.temporal? raise ScopedSearch::QueryNotSupported, "Unsupported type '#{field.type.inspect}')' for field '#{name}'. This can be a result of a search definition problem." end NUMERICAL_REGXP = /^\-?\d+(\.\d+)?$/ INTEGER_REGXP = /^\-?\d+$/ + UUID_REGXP = /^[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}$/ # Returns a list of appropriate fields to search in given a search keyword and operator. def default_fields_for(value, operator = nil) column_types = [:virtual] column_types += [:string, :text] if [nil, :like, :unlike, :ne, :eq].include?(operator) column_types += [:double, :float, :decimal] if value =~ NUMERICAL_REGXP column_types += [:integer] if value =~ INTEGER_REGXP + column_types += [:uuid] if value =~ UUID_REGXP column_types += [:datetime, :date, :timestamp] if (parse_temporal(value)) default_fields.select { |field| !field.set? && column_types.include?(field.type) } end