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
Related
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)
I just implemented friendly_id on the category model of rails app. Earlier it used to generate url like this:
localhost/search?category_id=208. Now I got it to generate url as below
localhost:3000/search?category_id=metal-processing-and-machine-tool
The url generating line is:
<a href="<%= search_equipments_path(:category_id => category.slug ) %>">
The search_equipments method is as follows:
def search_equipments
begin
if (params.keys & ['category_id', 'sub_category', 'manufacturer', 'country', 'state', 'keyword']).present?
if params[:category_id].present?
#category = Category.active.find params[:category_id]
else
#category = Category.active.find params[:sub_category] if params[:sub_category].present?
end
#root_categories = Category.active.roots
#sub_categories = #category.children.active if params[:category_id].present?
#sub_categories ||= {}
#countries = Country.active.all
#manufacturers = Manufacturer.active.all
#states = State.active.where("country_id = ?", params[:country]) if params[:country].present?
#states ||= {}
unless params[:category_id].present? && params[:sub_category].present?
params[:category_id] = #category.id if params[:category_id].present?
params[:sub_category] = #category.id if params[:sub_category].present?
end
#equipments = Equipment.active.filter(params.slice(:manufacturer, :country, :state, :category_id, :sub_category, :keyword)).order("#{sort_column} #{sort_direction}, created_at desc")
else
redirect_to root_path
end
rescue Exception => e
redirect_to root_path, :notice => "Something went wrong!"
end
end
Because of SEO reasons the people above me are telling to get rid off the _ which is in category_id from the url. I tried by changing the format in url generating line. Didn't help. Can please anyone tell me if it is doable and how can I achieve that?
Please let me know in the comments if any extra information needed.
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
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
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))