leikind / wice_grid

A Rails grid plugin to create grids with sorting, pagination, and (automatically generated) filters
MIT License
537 stars 215 forks source link

Filter on percentage field #202

Closed l3iodeez closed 9 years ago

l3iodeez commented 9 years ago

I have a field which contains a percentage stored as a decimal. I am able to change the values displayed in the grid by defining the column as:

g.column name:  '% Dmg', attribute: 'amtdamage', model: 'Material', auto_reload: false, html:   {class: 'smallgrid'} do |material|
number_to_percentage(material.amtdamage*100, precision: 0)
end 

This works fine, but unfortunately the filter is using the raw value from the table, not the value thats displayed.If I apply a filter like >1 it returns no records, but If I use >0.01 is works as expected. Is there a way to either A) process value of the filter so that if the user types >1 it will use >0.01 in the URL to retrieve the filtered page or B) define a column as amtdamage*100 and perform the filter on that?

leikind commented 9 years ago

There is no beautiful solution for this.

But you could modify params to convert 1 to .01. Ugly, yes, but it will work.

l3iodeez commented 9 years ago

Could this be accomplished with an external filter processor as described in the documentation? I think that is a new feature since I asked this question.

leikind commented 9 years ago

Could this be accomplished with an external filter processor as described in the documentation?

Yes, I think so.

I think that is a new feature since I asked this question.

What do you mean?

l3iodeez commented 9 years ago

I didn't see that section of the doc when I was trying to do this back in March. I got pulled onto another project and Im just circling back to this now. Either you added that feature recently or I overlooked it last time around. I just wanted to confirm that Im not misreading what is meant by an "external filter processor" since last time you said there is no "beautiful way" to do this. Is an external filter processor used to do math to the value the user enters in a filter box before passing it to the URL?

leikind commented 9 years ago

here are he docs https://github.com/leikind/wice_grid#defining-your-own-external-filter-processors

l3iodeez commented 9 years ago

Where do I put the ViewColumn and ConditionsGenerator classes? I put them in /lib/wice but my grid shows no filter at all for that column, so I assume I have them in the wrong place.

leikind commented 9 years ago

You put the in your app, wherever Rails can load files (app/controllers/ for instance) Just make sure you register them in the config, as described in the docs

l3iodeez commented 9 years ago

I moved the classes into /app/controllers but when I start the server I am getting "Error loading Wice::Defaults::ADDITIONAL_COLUMN_PROCESSORS. Class ViewColumnPercentage is not defined!"

This class is defined in /app/controllers/column_percentage.rb as is ConditionsGeneratorColumnPercentage so I must have something out of place.

In case it matters my column_percentage.rb is currently exactly the same as the column_integer.rb from the repo with just the class names and filename changed.

leikind commented 9 years ago

rename column_percentage.rb to view_column_percentage.rb

l3iodeez commented 9 years ago

Now I am getting: " Unable to load application: LoadError: Unable to autoload constant ViewColumnPercentage, expected /home/hdotson/nyeaportal/app/controllers/view_column_percentage.rb to define it"

Im sorry if I'm being thick, I really appreciate your taking time to assist. Im putting my view_column_percentage.rb below.

view_column_percentage.rb

 module Wice 

 module Columns #:nodoc:

class ViewColumnPercentage < ViewColumn #:nodoc:

  def render_filter_internal(params) #:nodoc:
    @contains_a_text_input = true

    @query, _, parameter_name, @dom_id = form_parameter_name_id_and_query(eq: '')

    opts = {size: 3, id: @dom_id, class: 'range-start'}

    opts[:class] += ' form-control input-sm'

    if auto_reload
      opts[:class] += ' auto-reload'
    end

    text_field_tag(parameter_name,  params[:eq], opts)
  end

  def yield_declaration_of_column_filter #:nodoc:
    {
      templates: [@query],
      ids:       [@dom_id]
    }
  end

  def has_auto_reloading_input? #:nodoc:
    auto_reload
  end
end

class ConditionsGeneratorColumnPercentage < ConditionsGeneratorColumn  #:nodoc:
  def get_op_and_value(val)
    num = nil
    op  = nil

    # remove spaces
    val = val.gsub(' ','')

    first_digit_or_dot_index = val =~ /[0-9.]/
    if first_digit_or_dot_index
      op = val[0...first_digit_or_dot_index]
      op = '=' if op == ''
      num = (Float(val[first_digit_or_dot_index..-1]))/100 rescue nil

      op = nil unless ['<','>','<=','>=','='].include?(op)
    end
    [op, num]
  end

  def  generate_conditions(table_alias, opts)   #:nodoc:
    unless opts.kind_of? Hash
      Wice.log "invalid parameters for the grid integer filter - must be a hash"
      return false
    end
    conditions = [[]]
    if opts[:eq]
      op, num = get_op_and_value(opts[:eq])
      if op && num
        conditions[0] << " #{@column_wrapper.alias_or_table_name(table_alias)}.#{@column_wrapper.name} " + op + " ? "
        conditions << num
      else
        opts.delete(:eq)
      end
    end

    if conditions.size == 1
      return false
    end

    conditions[0] = conditions[0].join(' and ')

    conditions
  end
end

  end
 end
leikind commented 9 years ago

Your file does not contain ViewColumnPercentage. You file contains Columns::ViewColumnPercentage. And in the config you instruct Rails to look for ViewColumnPercentage. Solve this issue. You don't need to have it in module Columns

Follow Rails naming conventions. How is Rails supposed to find ConditionsGeneratorColumnPercentage in file view_column_percentage.rb? It it simple. One class - one file. Class FooBar should be in file foo_bar.rb. Basic Rails knowledge, nothing related to WiceGrid

l3iodeez commented 9 years ago

Thanks for your help. I was following the example in the repo file /lib/wice/column_integer.rb so I thought it was necessary to put it in the columns module. I now have it set up as it should be (one class - one file) but Im still getting the error "Class ViewColumnPercentage is not defined!". I tried including them both inside the module "Wice", with no effect.

If I remove "< ViewColumn" and "< ConditionsGeneratorColumn" from these files I get a different error "ViewColumnPercentage should be inherited from Wice::Columns::ViewColumn!" so apparently it is finding the class definition, but something else must be going on.

I realize its likely that this is a result of my spotty familiarity with Rails, so I really appreciate your help if it turns out out have nothing to do with wice_grid.

EDIT: For anyone who finds this thread in the future the files shown below have been modified to be properly included in the wicegrid files.

view_column_percentage.rb:

     class ViewColumnPercentage < Wice::Columns::ViewColumn

    def render_filter_internal(params) #:nodoc:
      @contains_a_text_input = true

      @query, _, parameter_name, @dom_id = form_parameter_name_id_and_query(eq: '')

      opts = {size: 3, id: @dom_id, class: 'range-start'}

      opts[:class] += ' form-control input-sm'

      if auto_reload
        opts[:class] += ' auto-reload'
      end

      text_field_tag(parameter_name,  params[:eq], opts)
    end

    def yield_declaration_of_column_filter #:nodoc:
      {
        templates: [@query],
        ids:       [@dom_id]
      }
    end

    def has_auto_reloading_input? #:nodoc:
      auto_reload
    end

     end

conditions_generator_column_percentage.rb

   class ConditionsGeneratorColumnPercentage < Wice::Columns::ConditionsGeneratorColumn
   def get_op_and_value(val)
    num = nil
    op  = nil

    # remove spaces
    val = val.gsub(' ','')

    first_digit_or_dot_index = val =~ /[0-9.]/
    if first_digit_or_dot_index
      op = val[0...first_digit_or_dot_index]
      op = '=' if op == ''
      num = (Float(val[first_digit_or_dot_index..-1]))/100 rescue nil

      op = nil unless ['<','>','<=','>=','='].include?(op)
    end
    [op, num]
  end

  def  generate_conditions(table_alias, opts)   #:nodoc:
    unless opts.kind_of? Hash
      Wice.log "invalid parameters for the grid integer filter - must be a hash"
      return false
    end
    conditions = [[]]
    if opts[:eq]
      op, num = get_op_and_value(opts[:eq])
      if op && num
        conditions[0] << " #{@column_wrapper.alias_or_table_name(table_alias)}.#{@column_wrapper.name} " + op + " ? "
        conditions << num
      else
        opts.delete(:eq)
      end
    end

    if conditions.size == 1
      return false
    end

    conditions[0] = conditions[0].join(' and ')

    conditions
  end
 end
leikind commented 9 years ago
class ViewColumnPercentage < Wice::Columns::ViewColumn
class ConditionsGeneratorColumnPercentage < Wice::Columns::ConditionsGeneratorColumn
l3iodeez commented 9 years ago

That solved it. Thank you.