How to convert SQL syntax into Mongo? - ruby-on-rails

I use Ruby on Rails and Mongoid
How to convert this syntax to make it work with Mongo?
def index
#conversations = Conversation.where("sender_id = ? OR receiver_id = ?", current_user.id, current_user.id)
end
and
def index
#conversation.messages.where("user_id != ? AND read = ?", current_user.id, false).update_all(read: true)
end

found a solution:
#conversations = Conversation.where("sender_id = ? OR receiver_id = ?", current_user.id, current_user.id)
change to
#conversations = Conversation.any_of({sender_id: current_user.id}, {receiver_id: current_user.id})
The second line had to be completely rewritten and not used. So I don't know if it works or not
#conversation.messages.where("user_id != ? AND read = ?", current_user.id, false).update_all(read: true)
may not work
#conversation.messages.not.where(user_id: current_user.id).where(read: false).update_all(read: true)

Related

How to filter index for true value in Rails 4

I am trying to filter database index list by whether or not a value is true. Is this possible? Within the controller I am attempting this, which is not resolving to an error, but does not pull the index list I am looking for.
Controller:
def index
#people = Person.all
if params[:filter_by]
#people = Person.where(:position => params[:filter_by])
elsif
#people = Person.where(:ra_cs, params[:filter_by] == "true")
else
#people = Person.all
end
end
def person_params
params.require(:person).permit(
:fname, :lname, :user_name, :position, :title, :prefix, :focus1, :focus2, :focus3, :ra_cs, :ra_hn, :ra_mg, :ra_nb, :ra_ne)
end
The entry for the database is a checkbox, which inputs a value of 1 or 0 into the field.
I am not sure what other code might be involved, please let me know if I need to add anything else.
You need to refactor your code:
def index
if params[:filter_by].present?
case params[:filter_by]
when 'ra_cs'
#people = Person.where(ra_cs: true)
when 'ra_aa'
#people = Person.where(ra_aa: true)
when 'ra_bb'
#people = Person.where(ra_bb: true)
else
#people = Person.where(position: params[:filter_by])
end
else
#people = Person.all
end
end
Btw, elsif needs a condition.
Another option is using dynamic where where parameters.
def index
#people = Person.all
#people = #people.where(params[:filter_by] => true) if params[:filter_by].present?
end
If you don't what the user filtering by every attribute you could add a whitelist.
def index
#people = Person.all
allowed = %w[ra_cs ra_aa ra_bb ...]
#people = #people.where(params[:filter_by] => true) if params[:filter_by].in?(allowed)
end
In this second example you don't have to check for the presence, since nil or "" would be returned, which is not in allowed. Meaning that the if-statement would evaluate to false anyway.

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

rails apply where if variable is not nil else apply all - nicer way

How to optimize/refactor this rails code,
I want to apply where condition to the Country and the City if the co is not nil, if its nil, then apply all.
def pre(co = nil,ci = nil)
cond1 = co.nil? ? "all" : "where(:id => co)"
cond2 = ci.nil? ? "all" : "where(:id => ci)"
#countries = Country.send(cond1).order(:name).map{|i| [i.name,i.id]}
#cities = City.send(cond2).order(:name).map{|i| [i.name,i.id]}
end
Is it a nice way or is there a nicer way?
#countries = Country.where(co.nil? || {:id => co}).order(:name).map{|i| [i.name,i.id]}
#cities = City.where(ci.nil? || {:id => ci}).order(:name).map{|i| [i.name,i.id]}
You can try something like this
#country = Country
#city = City
if co.blank?
#country = #country.where(:id => co)
end
if ci.blank?
#city = #city.where(:id => ci)
end
#countries = #country.order(:name).all.map{|i| [i.name,i.id]}
#cities = #city.order(:name).all.map{|i| [i.name,i.id]}
You would think about something like this.
def pre(co = nil, ci = nil)
#countries = scopify(Country, co)
#cities = scopify(City, ci)
end
def scopify(model_or_scope, attribute)
scope = model_or_scope.scoped
scope = scope.where(:id => attribute) if attribute.present?
scope.order(:name).map { |s| [s.name, s.id] }
end

Pagination on multiple searches

I have the following bit of code:
def index
#games = Game.gamsearch(params[:gamsearch])
#games = Game.consearch(params[:consearch]) if params[:consearch].present?
#games = Game.gensearch(params[:gensearch]) if params[:gensearch].present?
#games = Game.where("game_name LIKE ?", "#{params[:game_name]}%") if params[:game_name].present?
#games = Game.where("console = ?", params[:console]) if params[:console].present?
end
What I wish to do is have all of these results paginate. Now I know how to paginate from a singular search as I have done here:
def index
user_relation = case params[:username].present?
when true then User.where("username LIKE ?", "#{params[:username]}%")
else User
end
#users = user_relation.paginate :page=>params[:page], :order => 'created_at desc', :per_page => 10
end
But the games controller has 5 possible methods of search and was wondering how I would apply pagination to it.
Any help would be great, thanks.
This should be possible by appending the search results all to the same array and than paginate this array.
like:
def index
#games = Array.new()
#games << Game.gamsearch(params[:gamsearch])
#games << Game.consearch(params[:consearch]) if params[:consearch].present?
#games << Game.gensearch(params[:gensearch]) if params[:gensearch].present?
#games << Game.where("game_name LIKE ?", "#{params[:game_name]}%") if params[:game_name].present?
#games << Game.where("console = ?", params[:console]) if params[:console].present?
end
and then just paginate the #games object.
hope this helps!

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))

Resources