putting a variable inside a string, it's not working? - ruby-on-rails

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.

Related

How to optimize queries and remove SQL Injection

I have following query
query = {}
if params[:post_id]
query.merge!('post_id' => "profiles.post_id = '#{params[:post_id]}'")
end
if params[:name].present?
query.merge!('name' => "name = '#{params[:name]}'")
end
if params[:gender].present?
query.merge!('gender' => "gender = '#{params[:gender}' ")
end
ProductPost.includes(:profiles).where("#{query.values.join(' and ') }").references(:profiles)
How to optimize above code and how to remove my SQL Injection.
I'm getting SQL Injection on every value of my HASH.
Thanks.
I would write something like this:
scope = ProductPost.includes(:profiles).references(:profiles)
scope = scope.where(profiles: { post_id: params[:post_id] }) if params[:post_id]
scope = scope.where(name: params[:name]) if params[:name]
scope = scope.where(gender: params[:gender]) if params[:gender]
scope

Use LIKE/regex with variable in mongoid

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

ActiveRecord condition syntax question

Is there a better way of writing this? Is it possible to do cleanly in one line?
conditions = ["category = ?", params[:category]] if params[:category]
#events = CalendarEvent.all( :conditions => conditions )
Not really too much to consolidate but you don't have a lot going on so shouldn't matter.
def action
options = {:conditions => ['category=?', params[:category]]} if params[:category]
#events = CalendarEvent.find(:all, options)
end
#events = CalendarEvent.all(
:conditions => (params[:category] ? ["category = ?", params[:category]] : nil))

check_box_tag and find condition

<%= check_box_tag('videos_count')%>
If this box is checked, the param will say "videos_count"=>"1" . In the controller I have this:
videos_count = params[:videos_count]
#cars = Car.paginate( :page => params[:page], :per_page => 10,
:conditions => ["videos_count = ?", videos_count],
when the box is checked I see the correct parameter in the server log, but the find returns all of the results instead of results with videos_count = 1.
Check the datatype of 'videos_count' if it's Tiny INT then following may worh. No checked though.
:conditions => ["videos_count = ?", true]
What will the output for this?
:conditions => ["videos_count = ?", 1])
I think there is an issue with your table.

Filtering ActiveRecord queries in rails

I'm used to Django where you can run multiple filter methods on querysets, ie Item.all.filter(foo="bar").filter(something="else").
The however this is not so easy to do in Rails. Item.find(:all, :conditions => ["foo = :foo", { :foo = bar }]) returns an array meaning this will not work:
Item.find(:all, :conditions => ["foo = :foo", { :foo = 'bar' }]).find(:all, :conditions => ["something = :something", { :something = 'else' }])
So I figured the best way to "stack" filters is to modify the conditions array and then run the query.
So I came up with this function:
def combine(array1,array2)
conditions = []
conditions[0] = (array1[0]+" AND "+array2[0]).to_s
conditions[1] = {}
conditions[1].merge!(array1[1])
conditions[1].merge!(array2[1])
return conditions
end
Usage:
array1 = ["foo = :foo", { :foo = 'bar' }]
array2 = ["something = :something", { :something = 'else' }]
conditions = combine(array1,array2)
items = Item.find(:all, :conditions => conditions)
This has worked pretty well. However I want to be able to combine an arbitrary number of arrays, or basically shorthand for writing:
conditions = combine(combine(array1,array2),array3)
Can anyone help with this? Thanks in advance.
What you want are named scopes:
class Item < ActiveRecord::Base
named_scope :by_author, lambda {|author| {:conditions => {:author_id => author.id}}}
named_scope :since, lambda {|timestamp| {:conditions => {:created_at => (timestamp .. Time.now.utc)}}}
named_scope :archived, :conditions => "archived_at IS NOT NULL"
named_scope :active, :conditions => {:archived_at => nil}
end
In your controllers, use like this:
class ItemsController < ApplicationController
def index
#items = Item.by_author(current_user).since(2.weeks.ago)
#items = params[:archived] == "1" ? #items.archived : #items.active
end
end
The returned object is a proxy and the SQL query will not be run until you actually start doing something real with the collection, such as iterating (for display) or when you call Enumerable methods on the proxy.
I wouldn't do it like you proposed.
Since find return an array, you can use array methods to filter it, on example:
Item.find(:all).select {|i| i.foo == bar }.select {|i| i.whatever > 23 }...
You can also achive what you want with named scopes.
You can take a look at Searchlogic. It makes it easier to use conditions on
ActiveRecord sets, and even on Arrays.
Hope it helps.
You can (or at least used to be able to) filter like so in Rails:
find(:all, :conditions => { :foo => 'foo', :bar => 'bar' })
where :foo and :bar are field names in the active record. Seems like all you need to do is pass in a hash of :field_name => value pairs.

Resources