Optional Rails Params in Controller Query - ruby-on-rails

I have a question in regards to Rails params. I currently have only one filter on one of my views that allows users to filter data by a date range. I am adding two more filters to that view so that users can filter by code and country. However, I want those filters to be optional.
My current query looks something like this:
#data = Games
.where("date BETWEEN ? AND ?", *date_range_array)
.includes(:synced_country)
.order(sort_column + " " + sort_direction)
.page(params[:page])
The params for code and country will be something like, params[:code] and params[:country]. I would like to put them in the query like:
#data = Games
.where("date BETWEEN ? AND ?", *date_range_array)
.where("unique_code in ?" params[:code])
.where("country in ?" params[:country])
.includes(:synced_country)
.order(sort_column + " " + sort_direction)
.page(params[:page])
The issue I am having is that if the user does not input anything for params[:code] and params[:country] I get an error because they are nil. Any idea on how to handle this kind of situation?

I would build it incrementally:
#data = Games.where("date BETWEEN ? AND ?", *date_range_array)
#data = #data.where("unique_code in ?", params[:code]) if params[:code]
#data = #data.where("country in ?", params[:country]) if params[:country]
#data = #data.includes(:synced_country)
.order(sort_column + " " + sort_direction)
.page(params[:page])
Note that you are missing two commas right before params[:code] and params[:country] which I've fixed in the above code.

#data = Games.where("date BETWEEN ? AND ?", *date_range_array).scoped
#data = #data.where("unique_code in ?" params[:code]).scoped if params[:code].present?
#data = #data.where("country in ?" params[:country]).scoped if params[:coutry].present?
#data = #data.includes(:synced_country)
.order(sort_column + " " + sort_direction)
.page(params[:page])
Anyway, I would move that complex query to a named scope or something inside the Game Model.
EDIT: added the "scoped" method, i'm not sure if needed, try it without .scoped if you want

I usually use the same method with Agis.
But sometimes I trend to use scope(as arieljuod said):
class Games
scope :in_contry, lambda{|contry| where("contry in ?", contry) if contry.present?}
scope :in_code, lambda{|code| where("unique_code in ?", code) if code.present?}
//other codes
end
//call lambdas as follows:
#data = Games.where("date BETWEEN ? AND ?", *date_range_array)
.in_code(params[:code])
.in_contry(params[:country])
.includes(:synced_country)
.order(sort_column + " " + sort_direction)
.page(params[:page])

Related

How can you set the order of the items in a nested array for an Active Record object?

Here's the code I have:
def show
#tournament = Tournament.find(params[:id])
#tournament.games = #tournament.games.order(sort_column + ' ' + sort_direction)
puts #tournament.games.inspect
end
I'm trying to sort the games in the tournament. If I do puts #tournament.games.order(sort_column + ' ' + sort_direction) it returns the games in the correct order. But I can't seem to actually change #tournament.games. I've tried the assignment, no assignment, order!, order without the !, and nothing seems to be working.

Search every field or attribute in model Rails

I have a simple model called Company with atributes such as Name, contact email, address, etc. I've created a search form where a user can find the company by searching for any attribute i.e., city, name of business, etc.
I'm new to Rails but I've figured out how to get it working like so in my controller.
if(params[:searchstring].present?)
logger.debug "*** Running search --> "
term = params[:searchstring]
#companies = Company.where('name LIKE ? OR name LIKE ? OR contactemail LIKE ? OR city LIKE ?' , "%#{term}%", "%#{term}%", "%#{term}%","%#{term}%" ).paginate(page: params[:page]).order('id DESC')
else
logger.debug "*** Running search --> get em all "
#companies = Company.all.paginate(page: params[:page], per_page: 5).order('id DESC')
end
end
This works fine but I'm guessing there is a much simplier way. I'd prefer not to modify the query every time I add an attribute. Any ideas on how to improve this?
You could go with something like this (It is just an example, might be a better way, but it is fonctionnal)
# company.rb
def self.search_all_properties term
query = ''
properties = Company.column_names
properties.each_with_index do |prop, index|
if index < properties.count - 1
query = query + prop + ' LIKE :term OR '
else
query = query + prop + ' LIKE :term'
end
end
term = "%" + term + "%"
Company.where(query, :term => term)
end
and use it like this
Company.search_all_properties term

Rails Simple Search

I have a basic search that is not working and I dont understand why.
In my model I have this
def self.search(search)
if search
search_condition = "%" + search + "%"
find(:all, :conditions => ['jobTitle LIKE ? OR jobDescription LIKE ?', search_condition, search_condition])
end
end
A parameter does get passed to it then an error comes up:
PG::InvalidTextRepresentation: ERROR: invalid input syntax for integer: "all" LINE 1: ...ngs".* FROM "postings" WHERE "postings"."id" IN ('all', '--... ^ : SELECT "postings".* FROM "postings" WHERE "postings"."id" IN ('all', '--- :conditions: - jobTitle LIKE ? OR jobDescription LIKE ? - "%drew%" - "%drew%" ')
Am I doing something wrong?
You are using outdated syntax for find. Use where instead:
def self.search(search)
if search
search_condition = "%" + search + "%"
where(['jobTitle LIKE ? OR jobDescription LIKE ?', search_condition, search_condition])
end
end

I need a search form with a large number of fields. How do I do this cleanly in Ruby on Rails?

I'm building a database application that tracks a lot of data for a Person, such as first_name, last_name, DOB, and 20+ more fields.
Users will need to be able to search for all of these fields. I'm having trouble writing clean code for this. The code below is what I have so far in my people_controller:
The data is submitted from a form_tag
def search
#people = Person.all
general_info_string = String.new
if(params[:first_name] != "") then general_info_string << 'people.first_name = "' + params[:first_name] + '" AND ' end
if(params[:last_name] != "") then general_info_string << "people.last_name = '" + params[:last_name] + "' AND " end
... Lots more of similar clauses
general_info_string = general_info_string[0, general_info_string.length - 5]
# ^This line removes the trailing " AND " from the string
#people = #people.where(general_info_string)
end
general_info_string is so called because there are more "where" clauses(not shown) and separate strings that I build to search for them.
The problem here is that the code looks like a mess and seems like a "hacky" way to do something that should be well supported by Rails. How could I perform this operation in a cleaner way?
That's not just hacky - it leaves you open to a string injection attack.
You need a :conditions using the ? template, like this example:
:conditions => ["key1 = ?", var]
but you need to make the template part into a string that grows once per parameter, and you need to make the var into an array that grows with each parameter's value. That gives you something like this:
template = []
values = []
if params[:first_name].present?
template.push 'people.first_name = ?'
values.push params[:first_name]
end
if params[:last_name].present?
template.push 'people.last_name = ?'
values.push params[:last_name]
end
template = template.join(' AND ')
:conditions => [template, *values]
From there, you should DRY up all those ifs, such as with a table of value keys. Then you'd loop through the table, check the key, and push its results into the arrays:
fields = [:first_name, :last_name, :shoe_size, ...]
fields.each do |field|
if params[field].present?
template.push "people.#{field} = ?"
values.push params[field]
end
end

request.raw_post trying to pull data from it

def search_results
#keyword = request.raw_post
#tutors = Tutors.find(:all,:conditions => ["first_name LIKE ?", '%' + "raul" + '%'])
end
I am trying to get some information out of request.raw_post, but it is giving me this long string: "authenticity_token=HxxkPMpSr0kHZOVZIYbpMti217BTeUa5G2vX8zbs8ig%3D&keyword=alex&authenticity_token=HxxkPMpSr0kHZOVZIYbpMti217BTeUa5G2vX8zbs8ig%3D."
Basically, I just to get "alex," where it says "keyword=alex." How can I do it?
If you want that value, I would suggest using params[:keyword].
Or alternatively, request.raw_post.split(/&/).grep(/keyword=/).first.split(/=/).last

Resources