Skip to content

Commit cae5b22

Browse files
committed
Reimplement and cleanup metarsearch mongoid adapter (still WIP though)
1 parent b4f51dd commit cae5b22

File tree

1 file changed

+57
-205
lines changed

1 file changed

+57
-205
lines changed

lib/meta_search/searches/mongoid.rb

Lines changed: 57 additions & 205 deletions
Original file line numberDiff line numberDiff line change
@@ -5,227 +5,79 @@
55
module MetaSearch
66
module Searches
77

8-
module Mongoid
9-
extend ActiveSupport::Concern
8+
require 'delegate'
9+
class MongoidSearchBuilder < SimpleDelegator
10+
def initialize relation, params, options
11+
super(relation)
12+
@relation = relation
13+
@params, @options = params, options
14+
end
1015

11-
def method_missing? name, *args, &block
12-
if name =~ metasearch_regexp
13-
field_name, condition = $1, $2
14-
raise [field_name, condition].inspect
15-
else
16-
super
16+
def build
17+
params.each_pair do |field_query, value|
18+
field, query = field_query.scan(metasearch_regexp).first
19+
case query.to_sym
20+
when :contains
21+
@relation = relation.where(field => /#{value}/)
22+
else
23+
raise [field_query, value].inspect
24+
end
1725
end
26+
self
27+
end
28+
29+
attr_reader :relation, :params, :options
30+
31+
def base
32+
self
1833
end
1934

35+
def klass
36+
relation
37+
end
38+
39+
def method_missing name, *attrs, &block
40+
relation.send(name, *attrs, &block)
41+
end
42+
43+
2044
def respond_to? name, include_private = false
21-
name =~ metasearch_regexp or super
45+
name.to_s =~ metasearch_regexp or super
2246
end
2347

24-
module ClassMethods
25-
def metasearch(params = nil, options = nil)
26-
options ||= {}
27-
params ||= {}
28-
raise [options, params] unless [options, params].all?(&:empty?)
29-
scoped
48+
def method_missing name, *args, &block
49+
if name =~ metasearch_regexp
50+
params[name]
51+
else
52+
super
3053
end
3154
end
3255

3356
def metasearch_regexp
34-
@metasearch_regexp ||= begin
35-
field_names = fields.map(&:last).map(&:name)
57+
field_names = klass.content_columns.map(&:name)
3658

37-
# general_conditions = %w[eq]
38-
# string_conditions = %w[starts_with ends_with contains]
39-
# id_conditions = []
40-
# checkbox_conditions = %w[in]
41-
# range_conditions = %w[gte lte]
42-
# number_conditions = %w[numeric]
43-
# boolean_conditions = %w[is_true is_false is_present is_blank is_null is_not_null]
59+
conditions = MetaSearch::DEFAULT_WHERES.map {|condition| condition[0...-1]} # pop tail options
60+
61+
/\A(#{field_names.join('|')})_(#{conditions.join('|')})/
62+
end
63+
64+
end
4465

45-
conditions = MetaSearch::DEFAULT_WHERES.map {|condition| condition[0...-1]} # pop tail options
66+
module Mongoid
67+
extend ActiveSupport::Concern
4668

47-
/\A(#{field_names.join('|')})_(#{conditions.join('|')})/
69+
module ClassMethods
70+
def metasearch(params = nil, options = nil)
71+
options ||= {}
72+
params ||= {}
73+
MongoidSearchBuilder.new(self, params, options).build
74+
# @metasearch_query
75+
# raise [params, options].inspect unless [options, params].all?(&:empty?)
76+
# scoped
4877
end
78+
alias_method :search, :metasearch unless respond_to?(:search)
4979
end
50-
end
5180

52-
# module Mongoid
53-
#
54-
# def self.included(base)
55-
# base.extend ClassMethods
56-
#
57-
# base.class_eval do
58-
# class_attribute :_metasearch_include_attributes, :_metasearch_exclude_attributes
59-
# class_attribute :_metasearch_include_associations, :_metasearch_exclude_associations
60-
# class_attribute :_metasearch_methods
61-
# self._metasearch_include_attributes =
62-
# self._metasearch_exclude_attributes =
63-
# self._metasearch_exclude_associations =
64-
# self._metasearch_include_associations = {}
65-
# self._metasearch_methods = {}
66-
# end
67-
# end
68-
#
69-
# module ClassMethods
70-
# # Prepares the search to run against your model. Returns an instance of
71-
# # MetaSearch::Builder, which behaves pretty much like an ActiveRecord::Relation,
72-
# # in that it doesn't actually query the database until you do something that
73-
# # requires it to do so.
74-
# #
75-
# # Options:
76-
# #
77-
# # * +params+ - a hash of valid searches with keys that are valid according to
78-
# # the docs in MetaSearch::Where.
79-
# # * +opts+ - A hash of additional information that will be passed through to
80-
# # the search's Builder object. +search_key+, if present, will override the
81-
# # default param name, 'search', in any sort_links generated by this Builder.
82-
# # All other keys are passed untouched to the builder, and available from the
83-
# # Builder's +options+ reader for use in :if blocks supplied to attr_searchable
84-
# # and friends.
85-
# def metasearch(params = nil, opts = nil)
86-
# builder = Searches.for(self).new(self, opts || {})
87-
# builder.build(params || {})
88-
# end
89-
#
90-
# alias_method :search, :metasearch unless respond_to?(:search)
91-
#
92-
# def _metasearch_method_authorized?(name, metasearch_object)
93-
# name = name.to_s
94-
# meth = self._metasearch_methods[name]
95-
# meth && (meth[:if] ? meth[:if].call(metasearch_object) : true)
96-
# end
97-
#
98-
# def _metasearch_attribute_authorized?(name, metasearch_object)
99-
# name = name.to_s
100-
# if self._metasearch_include_attributes.empty?
101-
# !_metasearch_excludes_attribute?(name, metasearch_object)
102-
# else
103-
# _metasearch_includes_attribute?(name, metasearch_object)
104-
# end
105-
# end
106-
#
107-
# def _metasearch_association_authorized?(name, metasearch_object)
108-
# name = name.to_s
109-
# if self._metasearch_include_associations.empty?
110-
# !_metasearch_excludes_association?(name, metasearch_object)
111-
# else
112-
# _metasearch_includes_association?(name, metasearch_object)
113-
# end
114-
# end
115-
#
116-
# private
117-
#
118-
# # Excludes model attributes from searchability. This means that searches can't be created against
119-
# # these columns, whether the search is based on this model, or the model's attributes are being
120-
# # searched by association from another model. If a Comment <tt>belongs_to :article</tt> but declares
121-
# # <tt>attr_unsearchable :user_id</tt> then <tt>Comment.search</tt> won't accept parameters
122-
# # like <tt>:user_id_equals</tt>, nor will an Article.search accept the parameter
123-
# # <tt>:comments_user_id_equals</tt>.
124-
# def attr_unsearchable(*args)
125-
# if table_exists?
126-
# opts = args.extract_options!
127-
# args.flatten.each do |attr|
128-
# attr = attr.to_s
129-
# raise(ArgumentError, "No persisted attribute (column) named #{attr} in #{self}") unless self.columns_hash.has_key?(attr)
130-
# self._metasearch_exclude_attributes = self._metasearch_exclude_attributes.merge(
131-
# attr => {
132-
# :if => opts[:if]
133-
# }
134-
# )
135-
# end
136-
# end
137-
# end
138-
#
139-
# # Like <tt>attr_unsearchable</tt>, but operates as a whitelist rather than blacklist. If both
140-
# # <tt>attr_searchable</tt> and <tt>attr_unsearchable</tt> are present, the latter
141-
# # is ignored.
142-
# def attr_searchable(*args)
143-
# if table_exists?
144-
# opts = args.extract_options!
145-
# args.flatten.each do |attr|
146-
# attr = attr.to_s
147-
# raise(ArgumentError, "No persisted attribute (column) named #{attr} in #{self}") unless self.columns_hash.has_key?(attr)
148-
# self._metasearch_include_attributes = self._metasearch_include_attributes.merge(
149-
# attr => {
150-
# :if => opts[:if]
151-
# }
152-
# )
153-
# end
154-
# end
155-
# end
156-
#
157-
# # Excludes model associations from searchability. This mean that searches can't be created against
158-
# # these associations. An article that <tt>has_many :comments</tt> but excludes comments from
159-
# # searching by declaring <tt>assoc_unsearchable :comments</tt> won't make any of the
160-
# # <tt>comments_*</tt> methods available.
161-
# def assoc_unsearchable(*args)
162-
# opts = args.extract_options!
163-
# args.flatten.each do |assoc|
164-
# assoc = assoc.to_s
165-
# raise(ArgumentError, "No such association #{assoc} in #{self}") unless self.reflect_on_all_associations.map {|a| a.name.to_s}.include?(assoc)
166-
# self._metasearch_exclude_associations = self._metasearch_exclude_associations.merge(
167-
# assoc => {
168-
# :if => opts[:if]
169-
# }
170-
# )
171-
# end
172-
# end
173-
#
174-
# # As with <tt>attr_searchable</tt> this is the whitelist version of
175-
# # <tt>assoc_unsearchable</tt>
176-
# def assoc_searchable(*args)
177-
# opts = args.extract_options!
178-
# args.flatten.each do |assoc|
179-
# assoc = assoc.to_s
180-
# raise(ArgumentError, "No such association #{assoc} in #{self}") unless self.reflect_on_all_associations.map {|a| a.name.to_s}.include?(assoc)
181-
# self._metasearch_include_associations = self._metasearch_include_associations.merge(
182-
# assoc => {
183-
# :if => opts[:if]
184-
# }
185-
# )
186-
# end
187-
# end
188-
#
189-
# def search_methods(*args)
190-
# opts = args.extract_options!
191-
# authorizer = opts.delete(:if)
192-
# args.flatten.map(&:to_s).each do |arg|
193-
# self._metasearch_methods = self._metasearch_methods.merge(
194-
# arg => {
195-
# :method => MetaSearch::Method.new(arg, opts),
196-
# :if => authorizer
197-
# }
198-
# )
199-
# end
200-
# end
201-
#
202-
# alias_method :search_method, :search_methods
203-
#
204-
# def _metasearch_includes_attribute?(name, metasearch_object)
205-
# attr = self._metasearch_include_attributes[name]
206-
# attr && (attr[:if] ? attr[:if].call(metasearch_object) : true)
207-
# end
208-
#
209-
# def _metasearch_excludes_attribute?(name, metasearch_object)
210-
# attr = self._metasearch_exclude_attributes[name]
211-
# attr && (attr[:if] ? attr[:if].call(metasearch_object) : true)
212-
# end
213-
#
214-
# def _metasearch_includes_association?(name, metasearch_object)
215-
# assoc = self._metasearch_include_associations[name]
216-
# assoc && (assoc[:if] ? assoc[:if].call(metasearch_object) : true)
217-
# end
218-
#
219-
# def _metasearch_excludes_association?(name, metasearch_object)
220-
# assoc = self._metasearch_exclude_associations[name]
221-
# assoc && (assoc[:if] ? assoc[:if].call(metasearch_object) : true)
222-
# end
223-
#
224-
# end
225-
# end
226-
#
227-
# def self.for(klass)
228-
# DISPATCH[klass.name]
229-
# end
81+
end
23082
end
23183
end

0 commit comments

Comments
 (0)