module ActiveScaffold::Finder::ClassMethods
Public Instance Methods
condition_for_column(column, value, text_search = :full)
click to toggle source
Generates an SQL condition for the given ActiveScaffold column based on that column's database type (or form_ui … for virtual columns?). TODO: this should reside on the column, not the controller
# File lib/active_scaffold/finder.rb, line 38 def condition_for_column(column, value, text_search = :full) like_pattern = like_pattern(text_search) value = value.with_indifferent_access if value.is_a? Hash if self.respond_to?("condition_for_#{column.name}_column") return send("condition_for_#{column.name}_column", column, value, like_pattern) end return unless column && column.search_sql && !value.blank? search_ui = column.search_ui || column.column.try(:type) begin sql, *values = if search_ui && self.respond_to?("condition_for_#{search_ui}_type") send("condition_for_#{search_ui}_type", column, value, like_pattern) else if column.search_sql.instance_of? Proc column.search_sql.call(value) else condition_for_search_ui(column, value, like_pattern, search_ui) end end return nil unless sql conditions = [column.search_sql.collect { |search_sql| sql % {:search_sql => search_sql} }.join(' OR ')] conditions += values * column.search_sql.size if values.present? conditions rescue StandardError => e logger.error "#{e.class.name}: #{e.message} -- on the ActiveScaffold column :#{column.name}, search_ui = #{search_ui} in #{name}" raise e end end
condition_for_datetime(column, value, like_pattern = nil)
click to toggle source
# File lib/active_scaffold/finder.rb, line 199 def condition_for_datetime(column, value, like_pattern = nil) conversion = datetime_conversion_for_condition(column) from_value = condition_value_for_datetime(column, value[:from], conversion) to_value = condition_value_for_datetime(column, value[:to], conversion) if from_value.nil? && to_value.nil? nil elsif !from_value ['%{search_sql} <= ?', to_value.to_s(:db)] elsif !to_value ['%{search_sql} >= ?', from_value.to_s(:db)] else ['%{search_sql} BETWEEN ? AND ?', from_value.to_s(:db), to_value.to_s(:db)] end end
condition_for_null_type(column, value, like_pattern = nil)
click to toggle source
# File lib/active_scaffold/finder.rb, line 223 def condition_for_null_type(column, value, like_pattern = nil) case value.to_s when 'null' ['%{search_sql} is null', []] when 'not_null' ['%{search_sql} is not null', []] end end
condition_for_numeric(column, value)
click to toggle source
# File lib/active_scaffold/finder.rb, line 89 def condition_for_numeric(column, value) if !value.is_a?(Hash) ['%{search_sql} = ?', condition_value_for_numeric(column, value)] elsif ActiveScaffold::Finder::NULL_COMPARATORS.include?(value[:opt]) condition_for_null_type(column, value[:opt]) elsif value[:from].blank? || !ActiveScaffold::Finder::NUMERIC_COMPARATORS.include?(value[:opt]) nil elsif value[:opt] == 'BETWEEN' ['(%{search_sql} BETWEEN ? AND ?)', condition_value_for_numeric(column, value[:from]), condition_value_for_numeric(column, value[:to])] else ["%{search_sql} #{value[:opt]} ?", condition_value_for_numeric(column, value[:from])] end end
condition_for_range(column, value, like_pattern = nil)
click to toggle source
# File lib/active_scaffold/finder.rb, line 103 def condition_for_range(column, value, like_pattern = nil) if !value.is_a?(Hash) if column.text? ["%{search_sql} #{ActiveScaffold::Finder.like_operator} ?", like_pattern.sub('?', value)] else ['%{search_sql} = ?', ActiveScaffold::Core.column_type_cast(value, column.column)] end elsif ActiveScaffold::Finder::NULL_COMPARATORS.include?(value[:opt]) condition_for_null_type(column, value[:opt], like_pattern) elsif value[:from].blank? nil elsif ActiveScaffold::Finder::STRING_COMPARATORS.values.include?(value[:opt]) ["%{search_sql} #{ActiveScaffold::Finder.like_operator} ?", value[:opt].sub('?', value[:from])] elsif value[:opt] == 'BETWEEN' ['(%{search_sql} BETWEEN ? AND ?)', value[:from], value[:to]] elsif ActiveScaffold::Finder::NUMERIC_COMPARATORS.include?(value[:opt]) ["%{search_sql} #{value[:opt]} ?", value[:from]] end end
condition_for_record_select_type(column, value, like_pattern = nil)
click to toggle source
# File lib/active_scaffold/finder.rb, line 215 def condition_for_record_select_type(column, value, like_pattern = nil) if value.is_a?(Array) ['%{search_sql} IN (?)', value] else ['%{search_sql} = ?', value] end end
condition_for_search_ui(column, value, like_pattern, search_ui)
click to toggle source
# File lib/active_scaffold/finder.rb, line 68 def condition_for_search_ui(column, value, like_pattern, search_ui) case search_ui when :boolean, :checkbox ['%{search_sql} = ?', column.column ? ActiveScaffold::Core.column_type_cast(value, column.column) : value] when :integer, :decimal, :float condition_for_numeric(column, value) when :string, :range condition_for_range(column, value, like_pattern) when :date, :time, :datetime, :timestamp condition_for_datetime(column, value) when :select, :multi_select, :country, :usa_state, :chosen, :multi_chosen ['%{search_sql} in (?)', Array(value)] else if column.text? ["%{search_sql} #{ActiveScaffold::Finder.like_operator} ?", like_pattern.sub('?', value)] else ['%{search_sql} = ?', ActiveScaffold::Core.column_type_cast(value, column.column)] end end end
condition_value_for_datetime(column, value, conversion = :to_time)
click to toggle source
# File lib/active_scaffold/finder.rb, line 139 def condition_value_for_datetime(column, value, conversion = :to_time) if value.is_a? Hash Time.zone.local(*[:year, :month, :day, :hour, :minute, :second].collect { |part| value[part].to_i }) rescue nil elsif value.respond_to?(:strftime) if conversion == :to_time # Explicitly get the current zone, because TimeWithZone#to_time in rails 3.2.3 returns UTC. # https://github.com/rails/rails/pull/2453 value.to_time.in_time_zone else value.send(conversion) end elsif conversion == :to_date Date.strptime(value, I18n.t("date.formats.#{column.options[:format] || :default}")) rescue nil else parts = Date._parse(value) format = I18n.translate "time.formats.#{column.options[:format] || :picker}", :default => '' if ActiveScaffold.js_framework == :jquery if format.blank? time_parts = [[:hour, '%H'], [:min, '%M'], [:sec, '%S']].collect { |part, format_part| format_part if parts[part].present? }.compact format = "#{I18n.t('date.formats.default')} #{time_parts.join(':')} #{'%z' if parts[:offset].present?}" else if parts[:hour] [[:min, '%M'], [:sec, '%S']].each { |part, f| format.gsub!(":#{f}", '') unless parts[part].present? } else value += ' 00:00:00' end format += ' %z' if parts[:offset].present? && format !~ /%z/i end if !parts[:year] && !parts[:month] && !parts[:mday] value = "#{Date.today.strftime(format.gsub(/%[HI].*/, ''))} #{value}" end value = translate_days_and_months(value, format) if I18n.locale != :en time = DateTime.strptime(value, format) rescue nil if time time = Time.zone.local_to_utc(time).in_time_zone unless parts[:offset] time = time.send(conversion) unless conversion == :to_time end time end unless value.nil? || value.blank? end
condition_value_for_numeric(column, value)
click to toggle source
# File lib/active_scaffold/finder.rb, line 179 def condition_value_for_numeric(column, value) return value if value.nil? value = column.number_to_native(value) if column.options[:format] && column.search_ui != :number case (column.search_ui || column.column.type) when :integer then value.to_i rescue value ? 1 : 0 when :float then value.to_f when :decimal then ActiveRecord::ConnectionAdapters::Column.value_to_decimal(value) else value end end
create_conditions_for_columns(tokens, columns, text_search = :full)
click to toggle source
Takes a collection of search terms (the tokens) and creates SQL that searches all specified ActiveScaffold columns. A row will match if each token is found in at least one of the columns.
# File lib/active_scaffold/finder.rb, line 11 def create_conditions_for_columns(tokens, columns, text_search = :full) # if there aren't any columns, then just return a nil condition return unless columns.any? like_pattern = like_pattern(text_search) tokens = [tokens] if tokens.is_a? String where_clauses = [] columns.each do |column| Array(column.search_sql).each do |search_sql| where_clauses << "#{search_sql} #{column.text? ? ActiveScaffold::Finder.like_operator : '='} ?" end end phrase = where_clauses.join(' OR ') tokens.collect do |value| columns.each_with_object([phrase]) do |column, condition| Array(column.search_sql).size.times do condition.push(column.text? ? like_pattern.sub('?', value) : ActiveScaffold::Core.column_type_cast(value, column.column)) end end end end
datetime_conversion_for_condition(column)
click to toggle source
# File lib/active_scaffold/finder.rb, line 191 def datetime_conversion_for_condition(column) if column.column column.column.type == :date ? :to_date : :to_time else :to_time end end
like_pattern(text_search)
click to toggle source
# File lib/active_scaffold/finder.rb, line 232 def like_pattern(text_search) case text_search when :full then '%?%' when :start then '?%' when :end then '%?' else '?' end end
translate_days_and_months(value, format)
click to toggle source
# File lib/active_scaffold/finder.rb, line 123 def translate_days_and_months(value, format) keys = { '%A' => 'date.day_names', '%a' => 'date.abbr_day_names', '%B' => 'date.month_names', '%b' => 'date.abbr_month_names' } keys.each do |f, k| if format.include? f table = Hash[I18n.t(k).compact.zip(I18n.t(k, :locale => :en).compact)] value.gsub!(Regexp.union(table.keys)) { |s| table[s] } end end value end