Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support to custom mappers #14

Closed
wagner opened this issue Jan 30, 2015 · 6 comments
Closed

Add support to custom mappers #14

wagner opened this issue Jan 30, 2015 · 6 comments

Comments

@wagner
Copy link

wagner commented Jan 30, 2015

I've hacked some code (https://github.com/wagner/search_cop/commit/e66ec0156fee0e0782f39eea1b2b94a0c2fe5b95) to allow a custom mapper for a brainspec/enumerize attribute:

class Comment < ActiveRecord::Base
  include SearchCop
  extend Enumerize

  belongs_to :user

  enumerize :state, in: {:new => 1, :approved => 2, :rejected => 3}, default: :new

  search_scope :search do
    ...
    options :state, :enumerator => Comment.state
  end
end

Comment.search("state: rejected")

But after I realized a custom mapper option could be more useful to everyone with similar needs. Something like this:

  search_scope :search do
    ...
    options :state, :mapper => lambda { |value| Comment.state.find_value(value).value }
  end

What do you think?

@mrkamel
Copy link
Owner

mrkamel commented Jan 31, 2015

I think this would be a nice feature. I'm not sure whether or not the naming :mapper => ... is fully self explanatory, but we'll find a proper solution.

The actual mapping should probably happen in https://github.com/mrkamel/search_cop/blob/master/lib/search_cop_grammar/attributes.rb

Wanna create a PR?

@wagner
Copy link
Author

wagner commented Feb 1, 2015

Sure! Are you ok with the Proc within the options hash?

@mrkamel
Copy link
Owner

mrkamel commented Feb 2, 2015

Sure, i'm fine with it

@westonganger
Copy link

+1

jakecraige added a commit to jakecraige/search_cop that referenced this issue Mar 24, 2017
This commit provides a low level extension point in the
hash structure to provide a lambda that returns the section of the query that
is being asked for.

This allows people to query for any DB types or operated that aren't directly
supported in SearchCop, and SearchCop doesn't have to support them.

It's a pretty low level API in that it expects you to know about what nodes and
visitors are, but this seems like a starting point that gets users past being
stuck, and could be built on in the future.

One of those things that I think could be useful is providing this same
structure, but as one of the `options` instead and that would be used every time
you query for that said attribute. The downside of the method proposed in this
PR is that you have to use the hash parser, and inline your SQL there and every
other place you want to use it. Providing it as a default option would allow
that.

Related to mrkamel#14, mrkamel#28 and mrkamel#31.
jakecraige added a commit to jakecraige/search_cop that referenced this issue Apr 21, 2017
This commit provides an extension point in the `search_scope` definition that
allows you to define a named `generator` that can be used with the hash
structure to perform arbitrary SQL queries.

This allows people to query for any DB types or operators that aren't directly
supported in SearchCop, and SearchCop doesn't have to support them.

Related to mrkamel#14, mrkamel#28 and mrkamel#31.
jakecraige added a commit to jakecraige/search_cop that referenced this issue Apr 21, 2017
This commit provides an extension point in the `search_scope` definition that
allows you to define a named `generator` that can be used with the hash
structure to perform arbitrary SQL queries.

This allows people to query for any DB types or operators that aren't directly
supported in SearchCop, and SearchCop doesn't have to support them.

Related to mrkamel#14, mrkamel#28 and mrkamel#31.
@westonganger
Copy link

This feature was added as part of #35

Example usage:

class Book
  include SearchCop

  enum types: {
    foo: 0,
    bar: 1,
  }
  
  search_scope :search do
    attributes :number, :my_enum
  
    generator :like_string do |column_name, raw_value|
      pattern = quote("%#{raw_value}%")
      "#{column_name} LIKE #{pattern}"
    end
  
    generator :match_type_enum do |column_name, raw_value|
      type_int = types[raw_value]
      "#{column_name} = #{type_int}"
    end
  end

end

Book.search(number: {like_string: "123"}, my_enum: {match_type_enum: "foo"})

@kylewelsby
Copy link

kylewelsby commented Jun 21, 2024

Here is another workaround for the enum issue.

class Book
  include SearchCop
  enum status: {draft: 0, published: 1, archived: 2}

  search_scope :search do |query|
    attributes :status
  end

  def self.search_with_enum(query)
    query = preprocess_query(query)
    search(query)
  end

  def self.preprocess_query(query)
    # Regular expression to match status queries with comparison operators
    query.gsub!(/status\s*(:|=|!=|>=|>|<=|<)\s*(\w+)/) do |match|
      operator = $1
      status_key = $2
      status_value = statuses[status_key]
      if status_value
        "status #{operator} #{status_value}"
      else
        match
      end
    end
    query
  end
end
Book.search_with_enum("status:published").to_sql
# => `SELECT "books".* FROM "books" WHERE ("books"."status" = 1)`

@wagner wagner closed this as completed Jul 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants