Passing params without nil - ruby-on-rails

I want to pass the value of a form to a Controller that should call a method from the Model for searching products.
I want to pass the category_id and the string that the user writes at the textfield.
I would pass to the model even the blank value of params (if the user doesn't write something on the search bar or choose none category)
I want to save even the blank value cause in the model, the SQL blank variable take "all" things.
And this is good a cause if there is something in the params , the SQL will find that thing, BUT if there is nothing in the params, the SQL will take all products.
I'm not able to save the value of params in varibiles cause if params is blank it returns to me this error:
undefined method `[]' for nil:NilClass
I hope you understand me and what I want to do.
In other words , I want to use a simple assignment to pass a value (even blank values) to a model to do a SQL query. In one shoot of code I want to program two cases.
Here my code.
In my Controller:
...
if params[:search]
#search_name = params[:search]
end
if params[:category][:name]
#category = params[:category][:name]
end
#products = Product.search(#search_name,#category)
...
In my Model:
def self.search(search_name,category)
ricerca = Product.where("category_id = ? ",category)
ricerca = ricerca.where("title like ? ", "%#{search_name}%")
end

You can get category parameters by defining a method like,
def category_params
params.fetch(:category, {})
end
And, then look up for Products by,
#search_name = params[:search]
#category = category_params[:name]
#products = Product.search(#search_name, #category)
In my opinion, if you are making a direct query on Product, then you should do like,
def product_params
params.fetch(:product, {})
end
#category = product_params[:category_id]
#title = product_params[:title]
#products = Product.search(#category, #title)
And in product model,
def self.search(category, title)
where("category_id = ? AND title LIKE ?", category, "%#{title}%")
end

Try this:
#search_name = params[:search]
#category = (params[:category].blank? ? nil : params[:category][:name])
#products = Product.search(#search_name,#category)

#Vito, change the line -> #category = params[:category][:name] in your controller by
#category = params[:category].present? ? params[:category][:name]
the issue is when you don't select the category then params[:category] comes nil and you are fetching name from params[:category] that's why error "undefined method `[]' for nil:NilClass" is comming.
Hope this will resolve your problem.

i still have problems , cause when i wrote
if params[:category]
#category = params[:category][:name]
else
#category = " "
end
if params[:search]
#nome_ricerca = params[:search]
else
#nome_ricerca = " "
end
#products = Product.search(#nome_ricerca,#category)
i have this problem:
Showing C:/Bitnami/depot/app/views/store/index.html.erb where line #18 raised:
undefined method `name' for "":String
Extracted source (around line #18):
<p>
<%= label_tag :search, 'Search:' %>
<%= text_field_tag :search, params[:search] %>
<%= collection_select :category, :name, Category.all, :id, :name, {:prompt => 'All Categories'} %>
<%= submit_tag "Search", name: nil %>
</p>
what is this?

Ok, i fixed the problem
it was (i think) concerning the fact that i used #category as variable name
maybe the view gets in confusion for this
i call #category in #cat and the problem disappears
But , now the problem is that the SQL query doesn't return all the category if i pass "" in the variable #cat
How can i have all the result of a query? with like %% it works but with
category_id = "" no. why?
I post the code fixed for others:
In Controller:
if params[:category]
#cat = params[:category][:name]
else
#cat = ''
end
if params[:search]
#nome_ricerca = params[:search]
else
#nome_ricerca = ''
end
#products = Product.search(#nome_ricerca,#cat)
In model:
def self.search(nome_ricerca,categoria)
ricerca = Product.where("title like ? AND category_id = ? ", "%#{nome_ricerca}%",categoria)
end

LAST POST:
PROBLEM FIXED:
In Controller
#stringa_sql = ""
if params[:search]
#nome_ricerca = params[:search]
else
#nome_ricerca = ''
end
#stringa_sql = "title like "+"'%"+#nome_ricerca+"%'"
if params[:category]
if params[:category][:name] != ""
#cat = params[:category][:name]
#stringa_sql += " AND category_id = "+#cat
else
#cat = ''
end
end
#products = Product.search(#stringa_sql)
In Model:
def self.search(stringa_sql)
ricerca = Product.where(stringa_sql)
end
Question: does this solution suffer Sql Injection ?
Thx all :)
I Hope this solution will help someone.

Related

undefined method `each' for nil:NilClass for order method

I get this error when I try to run my code. From what I've researched my problem is either in my controller or my view
This is my controller
class AppointmentsController < ApplicationController
def index
#appointments = Appointment.order('appt_time ASC')
#appointment = Appointment.new
end
end
This is my view
%h1 React Calendar
%h2 Appointments
%h3 Make a new appointment
= form_for #appointment do |f|
= f.text_field :title
= f.text_field :appt_time
= f.submit 'Make appointment'
= #appointmets.each do |a|
%h3 = a.title
%p = a.appt_time
I'm running
Rails 5.1.3
Ruby 2.4.1
Undefined method <method name> for nil:NilClass means you are calling that method, in this case .each, on something that does not exist (Nil).
In this case it is just because you have a typo in your view so the variable is not there like you think it is.
= #appointmets.each do |a|
%h3 = a.title
%p = a.appt_time
needs to be
= #appointments.each do |a| <--- you missed the "n"
%h3 = a.title
%p = a.appt_time

How to get rid off underscore "_" from the rails generated url?

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.

ActiveRecord::StatementInvalid in Show Controller

I've got a simple search form, in rails 4 app, that needs two params passed to be able to show relevant data.
I'm getting an 'Mysql2::Error: Unknown column 'data inputted' but the columns do exist. If I instead of '#search = Page.where(params[:one] && params[:two])' use '#search = Page.all' the data shows, but all of it shows.
Form
<%= form_tag(page_show_path, id: "search-form") do %>
<%= text_field_tag :one, params[:one], placeholder: "One" %>
<%= text_field_tag :two, params[:two], placeholder: "Two" %>
<%= submit_tag "Search", :name => nil %>
<% end %>
Model
def self.one(query)
where("one = ?", "%#{query}%")
end
def self.two(query)
where("two = ?", "%#{query}%")
end
Controller
def show
if (params[:one] && params[:two]).present?
#search = Page.where(params[:one] && params[:two])
else
redirect_to page_path, notice: "Not a valid combination"
end
end
You can Create and Use Scope.
scope :find_one_two, ->(query_one, query_two) { where("one = ? AND two = ? ", query_one, query_two) }
#search = Page.find_one_two(params[:one], params[:two])
OR
You can use.
#search = Page.where("one = ? AND two = ?", params[:one], params[:two])
def show
if (params[:one] && params[:two]).present?
#search = Page.where("one like ? AND two like ? ", "%#{params[:one]}%", "%#{params[:two]}%")
else
redirect_to page_path, notice: "Not a valid combination"
end
end
This may solve your problem.

Search by full name

I am trying to write a query that finds clients by their full name.
I have a model named Client with first name, last name, and middle name fields.
I also have this client_full_name method in my User model :
def client_full_name
"#{self.Client_fname} #{self.Client_mi} #{self.Client_lname}"
end
# FOR SEARCHES
def self.search_by_client_full_name(query)
where("client_full_name like ?", "%#{query}%")
end
I have this in my controller
def index
#FOR SEARCHES
if params[:search]
#clients = Client.search_by_client_full_name(params[:search])
else
#clients = Client.all
end
end
And I have this in my Index
<h2>Search for Clients</h2>
<%= form_tag(clients_path, :method => "get", id: "search-form") do %>
Search by Client Name: <br />
<%= text_field_tag :search, params[:search], placeholder: "Search Clients" %>
<%= submit_tag "Search", :client_full_name => nil %>
<% end %>
This is the Error that I keep getting
SQLite3::SQLException: no such column: client_full_name: SELECT "clients".* FROM "clients" WHERE (client_full_name like '%John Smith%')
Thank you for the help.
This can be solution for your question.
patient_first_name_cont = "Ajay"
patient_last_name_cont = "Kumar"
shared_context = Ransack::Context.for(Request)
search_parents = Request.includes(:request_status).ransack(
{ patient_first_name_cont: patient_first_name_cont }, context: shared_context
)
search_children = Request.includes(:request_status).ransack(
{ patient_last_name_cont: patient_last_name_cont }, context: shared_context
)
shared_conditions = [search_parents, search_children].map { |search| Ransack::Visitor.new.accept(search.base)}
#req = Request.joins(shared_context.join_sources).where(shared_conditions.reduce(&:and))
You method client_full_name is an instance method of class Client:
def client_full_name
"#{self.Client_fname} #{self.Client_mi} #{self.Client_lname}"
end
It ( client_full_name ) is not a column(at least it doesn't appear to be) of your clients table. That's why you're getting this error:
SQLite3::SQLException: no such column: client_full_name: SELECT "clients".* FROM "clients" WHERE (client_full_name like '%John Smith%')
to make your query work, you need to change your method search_by_client_full_name to this(NOTE- Query below will work only for MySQL):
def self.search_by_client_full_name(query)
where("CONCAT_WS(' ', Client_fname, Client_mi, Client_lname) LIKE :q", :q => "%#{query}%")
end
For SQLite you can use || for concatenation:
def self.search_by_client_full_name(query)
where("(Client_fname || Client_mi || Client_lname) LIKE :q", :q => "%#{query}%")
end
But || will return NULL if any of the column has NULL, to avoid that you'll have to write case

Ransack eq_any for boolean values

I have a model that has a boolean field called ignored. What I did right up to this point is not display records which have this field set to true by having a default_scope where(:ignored => false).
Now, in my Ransack search form I would like to have a checkbox named Include ignored so the table would also display the records which are ignored along with the ones which aren't.
I got as far as adding the checkbox to my search form f.check_box(:ignored_eq) but when checking this, the list will display ONLY the ignored records. How do I display records in all states when checking this box?
Controller:
def index
#q = Venue.search(params[:q])
#venues = #q.result.page(params[:page]).per_page(15)
end
Search form (HAML):
= search_form_for #q, url: [:admin, :venues] do |f|
= f.text_field :name_cont
= f.text_field :locality_name_cont
= f.text_field :categories_name_cont
= f.check_box :ignored_eq
= content_tag :button, type: :submit, class: 'btn' do
= content_tag(:i, "", class: "icon-search")
= t("helpers.links.search")
The desired functionality is: when I enter the page I want to have only the ones that have ignore = false listed and have the box unchecked. When I check the box and submit the form I want to have ignored as well as non-ignored ones displayed. Is this possible with Ransack?
What you can do is use the rewhere AR method.
and have something like that for the ignored flag:
def index
#q = Venue.search(params[:q])
#q = #q.rewhere("ignored = 0 OR ignored = 1") if params[:ignored_eq] == 1
#venues = #q.result.page(params[:page]).per_page(15)
end
you can also use the unscoped method to clear the default_scope
def index
if params[:ignored_eq] == 1
#q = Venue.unscoped.search(params[:q])
else
#q = Venue.search(params[:q])
end
#venues = #q.result.page(params[:page]).per_page(15)
end
which is prettier (IMO)

Resources