request.raw_post trying to pull data from it - ruby-on-rails

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

Related

How to use like clause query in rails?

I wanted to get a json format of the data when searching for the keyword so I use LIKE clause and query like this
"select * from employees where fname like ? or mname like ? or lname like ? or username like ? or id like ?", str, str, str, str, str
but I want to code it using rails. I have this code in my controller
def showemployees
str = params[:str]
render json: #employee = Employee.where(Employee.employees[:fname].matches("%#{str}%")) or
(Employee.employees[:mname].matches("%#{str}%")) or
(Employee.employees[:lname].matches("%#{str}%")) or
(Employee.employees[:id].matches("%#{str}%"))
end
and this code in my config/routes.rb
get 'employees/showemployees'
root :to => 'employees#new'
resources :employees
post 'employees/update_info'
when i type this, http://localhost:3000/employees/showemployees?str=samplename, a json format of the record should appear yet I got this error message
undefined method `employees' for #<Class:0x8e38900>
app/controllers/employees_controller.rb:6:in `showemployees'
where line 6 has this code
render json: #employee = Employee.where(Employee.employees[:fname].matches("%#{str}%")) or
You can chain where queries, but this AND each where query results
Employee.where('fname LIKE ?', "%#{str}%").where('lname LIKE ?', "%#{str}%").where('mname LIKE ?', "%#{str}%").where('username LIKE ?', "%#{str}%").where('id LIKE ?', "%#{str}%")
or to use OR clause
Employee.where('fname LIKE ? OR lname LIKE ? OR mname', "%#{str}%", "%#{str}%", "%#{str}%")

routing and searching a db ruby

I want to retrieve all the tweets that have a certain hashtag in them.
At first I add the hashtags in my 2 tables :
def add_hashtags(tweet)
tweet.content.scan(/(?:\s|^)(?:#(?!(?:\d+|\w+?_|_\w+?)(?:\s|$)))(\w+)(?=\s|$)/){ |tag|
#allhashes = Hashtag.all
#hash = Hashtag.find_by_name(tag[0].strip)
unless #hash
#hashtag = Hashtag.new(name: tag[0].strip)
#hashtag.save
#hashrel = Hashrelation.new(tweet_id: tweet.id, hashtag_id: #hashtag.id)
#hashrel.save
else
#hashrel = Hashrelation.new(tweet_id: tweet.id, hashtag_id: #hash.id)
#hashrel.save
end
}
end
then I want to route to the show method of tweet controller :
get 'tweets/show/(.:format)' => 'tweets#show', as: :hashtag
The links in the hashtags are as follows:
def twitify(tweet = '')
tweet.gsub(/(?:\s|^)(?:#(?!(?:\d+|\w+?_|_\w+?)(?:\s|$)))(\w+)(?=\s|$)/) do |tag|
" " + link_to("#{tag.strip}", hashtag_path(tag.strip), {:name => tag.strip})
end.html_safe
end
And finally the show method of the tweet controller is :
def show
#hashtag = Hashtag.find_by_name(params[:name])
#tweet_ids = Hashrelation.find_by_hashtag_id(#hashtag.id)
#feed_items = Tweet.find_by_id(#tweets_ids.id)
end
When I click on the link I get :
undefined method `id' for nil:NilClass
which means that params[:name] is either nill or it isn't like the one I have in the DB.
Could you guys help me figure this out ?
The link I see that is called is 'http://localhost:3000/tweets/show/.%23dadawea' which means I have extra things why would I ?.
I would do the following
def add_hashtags(tweet)
tweet.content.scan(/(?:\s|^)(?:#(?!(?:\d+|\w+?_|_\w+?)(?:\s|$)))(\w+)(?=\s|$)/).flatten.each do |tag|
hashtag = Hashtag.where(name: tag.strip).first_or_create
Hashrelation.create(tweet_id: tweet.id, hashtag_id: hashtag.id)
end
end
Then change the twitify method to look like
def twitify(tweet = '')
tweet.gsub(/(?:\s|^)(?:#(?!(?:\d+|\w+?_|_\w+?)(?:\s|$)))(\w+)(?=\s|$)/) do |tag|
" " + link_to("#{tag.strip}", hashtag_path(name: tag.strip))
end.html_safe
end
And the show method
def show
#hashtag = Hashtag.find_by_name(params[:name])
#tweet_ids = Hashrelation.where(hashtag_id: #hashtag.id).pluck(:id)
#feed_items = Tweet.where(tweet_id: #tweets_ids)
end
This should be what you are looking for. Now for whats changing:
Removed Duplicate logic in the add_hashtags to use create instead.
twitify method is passing name as an html option not a url option so I fixed that. Right now it thinks you want to set the format to the name of the hashtag and name the link the name of the hashtag**
show method is using find_by which will only return a single result not what you wnat for tweet_ids so i changed it to where clause and just grabbed the ids. Then changes feed_items to search Tweet for all tweet_ids in the Array.
To strip the # just use tag.strip[1..-1]

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

Optional Rails Params in Controller Query

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

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

Resources