Use LIKE/regex with variable in mongoid - ruby-on-rails

I'm trying to find all documents whose text contains the word test. The below works fine:
#tweets = Tweet.any_of({ :text => /.*test.*/ })
However, I want to be able to search for a user supplied string. I thought the below would work but it doesn't:
searchterm = (params[:searchlogparams][:searchterm])
#tweets = Tweet.any_of({ :text => "/.*"+searchterm+".*/" })
I've tried everything I could think of, anyone know what I could do to make this work.
Thanks in advance.

searchterm = (params[:searchlogparams][:searchterm])
#tweets = Tweet.any_of({ :text => Regexp.new ("/.*"+searchterm+".*/") })
or
searchterm = (params[:searchlogparams][:searchterm])
#tweets = Tweet.any_of({ :text => /.*#{searchterm}.*/ })

There is nothing wrong with the mongodb regex query. The problem is passing variable to ruby regex string. You cannot mix string with regex like normal strings
Instead
"/.*"+searchterm+".*/"
try this
>>searchterm = "test"
>>"/#{searchterm}/"
>> "/test/"

#tweets = Tweet.any_of({ :text => Regexp.new (".*"+searchterm+".*") })
is ok and have result

This worked for me by doing:
Model.find(:all, :conditions => {:field => /regex/i})

#tweets = Tweet.any_of({ :text => Regexp.new ("/.*"+searchterm+".*/") })
is work, but no result
#tweets = Tweet.any_of({ :text => Regexp.new (".*"+searchterm+".*") })
is ok and have result
#tweets = Tweet.any_of({ :text => /.*#{searchterm}.*/ })
is work, no result
My mongoid version is 3.1.3 and ruby version is 1.9.3

Related

How can i save the conditions in variable and use that variable in rails active record?

I am trying to save the conditions in a variable and call that in the active record query as shown below
if !key1.nil?
#condition = ":key2 => #value2, :key3 => #value3"
else
#condition = ":key4 => #value4, :key5 => #value5"
end
#result = Model.where(#condition).all
How can i do this? please help me.
UPDATE:
#condition = { "key1 = ? and key2 >= ? and key3 <= ? and id IN (?)", #value1, #value2, #value3, #id }
Use hash instead of string:
#condition = { :key2 => #value2, :key3 => #value3 }
Also, you could probably simplify the syntax of if !key1.nil? by using unless:
#condition = {}
unless key1
#condition = { :key2 => #value2, :key3 => #value3 }
else
#condition = { :key4 => #value4, :key5 => #value5 }
end

Check for dash before applying titleize in Rails

I am really new to Ruby and Rails and need to know how to check if a string contains a dash before applying titlelize.
#city = City.first :conditions => { :title => params[:city].titleize }
What I need to do is:
#city = City.first :conditions => { :title => params[:city] }
and then write something that will apply titleize ONLY if the #city variable doesn't contain a dash.
I like this solution added by zachrose a couple of weeks ago: https://gist.github.com/varyonic/ccda540c417a6bd49aec
def nice_title(phrase)
return phrase if phrase =~ /^-+$/
phrase.split('-').map { |part|
if part.chars.count == part.bytes.count
part.titleize
else
part.split(' ').map { |word| word.mb_chars.titleize }.join(' ')
end
}.join('-')
end
if params[:city] =~ /-/
#city = City.first :conditions => { :title => params[:city] }
else
#city = City.first :conditions => { :title => params[:city].titleize }
end
I do not know why you are using this, but I believe it will not work for all cases. There should be a better approach.

Search ignoring certain blank parameters

I have a simple search action that has 3 parameters and a where method to search a model. If I search and some of the parameters are nil, it will not return the records I want. I want it to search the database by only using the parameters that are not nil/blank. So if only one category is entered and sent in the parameters, I want my controller to ignore the other two parameters. However, if the other parameters are present, I want them to be included in the search.
I've tried many approaches but I can't get it to work properly. Here's my code.
hash = []
cat = :category_id => params[:category_id]
col = :color_id => params[:color_id]
brand = :brand_id => params[:brand_id]
if params[:category_id].present?
hash += cat
end
if params[:color_id].present?
hash += col
end
if params[:brand_id].present?
hash += brand
end
#results = Piece.where(hash).preload(:item).preload(:user).group(:item_id).paginate(:page => params[:page], :per_page => 9)
I've put the variables into strings and hashs, called to_a, joined them with (","). Nothing works.
Thanks
Try this code.
criteria = { :category_id => params[:category_id], :color_id => params[:color_id],
:brand_id => params[:brand_id] }.select { |key,value| value.present? }
#results = Piece.where(criteria).preload(:item).preload(:user).group(:item_id).
paginate(:page => params[:page], :per_page => 9)

putting a variable inside a string, it's not working?

I have a string stored in session[:login] that I want used in a SQL query, so I wrote this.
#users = User.find(:all, :conditions => ['user = "#{session[:login]}"'])
why doesn't this work? Thanks!
You can rebuild your query this way:
#users = User.find(:all, :conditions => ['user = ?', session[:login]])
But this one looks better:
#users = User.where(user: session[:login])
This is just a string without any variable interpolation: 'user = "#{session[:login]}"'
A string with variable interpolation looks like this: "user = '#{session[:login]}'"
Can you try this
#users = User.find(:all, :conditions => ["user = '#{session[:login]}' "])
use double quotes externly and internly single quotes.

Eval alternative

I have a bazillion controllers in my app, and I was wondering about using some metaprogramming to make maintenance less of a headache. This works, but it's spiked with danger in the form of eval:
def plural_action(method_name)
class_name = self.class.to_s.gsub( %r{^(\w*)Controller} ) {|s| $1 }
#title = "#{method_name.to_s.titlecase} of #{class_name}"
eval "#q = #{class_name.singularize}.where(:client_id => current_user.client_id).search(params[:q])"
eval "##{class_name.downcase} = #q.result(:distinct => true).paginate(:page => params[:page])"
eval "session[:query] = ##{class_name.downcase}.map(&:id)"
eval "respond_with(##{class_name.downcase})"
end
Can I do this without using eval? I've tinkered with instance_variable_set, send and const_get but no luck so far.
Here's an example of what I'd like the method to eval to.
def index
#title = "Index of Books"
#q = Book.where(:client_id => current_user.client_id).search(params[:q])
#books = #q.result(:distinct => true).paginate(:page => params[:page])
session[:query] = #books.map(&:id)
respond_with(#books)
end
There's a magnificent method constantize which turns a string into the constant (of which class types are an example) it represents. With that in mind, I think you could rewrite your method as:
def plural_action(method_name)
class_name = self.class.to_s.gsub( %r{^(\w*)Controller} ) {|s| $1 }
#title = "#{method_name.to_s.titlecase} of #{class_name}"
#q = class_name.singularize.constantize.where(:client_id => current_user.client_id).search(params[:q])
self.instance_variable_set("##{class_name.downcase}", #q.result(:distinct => true).paginate(:page => params[:page]))
session[:query] = self.instance_variable_get("##{class_name.downcase}").map(&:id)
respond_with(self.instance_variable_get("##{class_name.downcase}"))
end
def plural_action(method_name)
class_name = self.class.to_s.gsub( %r{^(\w*)Controller} ) {|s| $1 }
#title = "#{method_name.to_s.titlecase} of #{class_name}"
#q = class_name.singularize.constantize.where(:client_id => current_user.client_id).search(params[:q])
instance_variable_set class_name.downcase, #q.result(:distinct => true).paginate(:page => params[:page])
session[:query] = #q_result.map(&:id)
respond_with(#q_result)
end

Resources