How should I write case statement depend of parameters key? - mysql

For example I have index action:
def index
if params[:query]
#pharmaceutics = Pharmaceutic.where("name LIKE ?", params[:query])
elsif params[:code]
#pharmaceutics = Pharmaceutic.where("barcode LIKE ?", params[:code])
else
#pharmaceutics = Pharmaceutic.all
end
end
And when I send two params: code and query I would like to filter my Pharmaceutics using both of them. I have MySQL database.

I would probably use scoped method, like this:
def index
scope = Pharmaceutic.scoped # Pharmaceutic.all if you use Rails 4
scope = scope.where('name LIKE ?', params[:query]) if params[:query].present?
scope = scope.where('barcode LIKE ?', params[:code]) if params[:code].present?
#pharmaceutics = scope
end
You can also write your custom scopes and replace where(...) with them to make the code clearer.

Related

How to define variable outside method that is present inside method?

I'm trying to create a method that allows me to query SQL in ruby without typing results = client.query('code') for every query. Heres my current method but it says that results are undefined in my puts statement. When I don't use my method it works normally.
require "mysql2"
client = Mysql2::Client.new(:username => 'buck19j')
def sql(code)
client = Mysql2::Client.new(:username => 'buck19j')
results = client.query(code)
end
sql('SHOW DATABASES')
puts(results.to_a)
How to define variable outside method that is present inside method?
Make the method return the value, not assign it:
def sql(code)
client = Mysql2::Client.new(:username => 'buck19j')
client.query(code)
end
Then assign a variable when you call the method:
results = sql('SHOW DATABASES')
puts(results.to_a)
results doesn't "go out" the sql method, because is a local variable. An approach would be to define it as an instance variable, and you could use then as you do with puts (still unclear what's the whole context of this).
def sql(code)
client = Mysql2::Client.new(:username => 'buck19j')
#results = client.query(code)
end
sql('SHOW DATABASES')
puts(#results.to_a)
Other way would be just leave the function returns the client.query(code) value:
def sql(code)
client = Mysql2::Client.new(:username => 'buck19j')
client.query(code)
end
puts(sql('SHOW DATABASES').to_a)

Rails custom query based on params

I have zero or many filter params being sent from a json request.
the params may contain:
params[:category_ids"]
params[:npo_ids"]
etc.
I am trying to retreive all Projects from my database with the selected ids. Here is what I have currently:
def index
if params[:category_ids].present? || params[:npo_ids].present?
#conditions = []
#ids = []
if params["category_ids"].present?
#conditions << '"category_id => ?"'
#ids << params["category_ids"].collect{|x| x.to_i}
end
if params["npo_ids"].present?
#conditions << '"npo_id => ?"'
#ids << params["npo_ids"].collect{|x| x.to_i}
end
#conditions = #ids.unshift(#conditions.join(" AND "))
#projects = Project.find(:all, :conditions => #conditions)
else ...
This really isn't working, but hopefully it gives you an idea of what I'm trying to do.
How do I filter down my activerecord query based on params that I'm unsure will be there.
Maybe I can do multiple queries and then join them... Or maybe I should put a filter_by_params method in the Model...?
What do you think is a good way to do this?
In rails 3 and above you build queries using ActiveRelation objects, no sql is executed until you try to access the results, i.e.
query = Project.where(is_active: true)
# no sql has been executed
query.each { |project| puts project.id }
# sql executed when the first item is accessed
The syntax you are using looks like rails 2 style; hopefully you are using 3 or above and if so you should be able to do something like
query = Project.order(:name)
query = query.where("category_id IN (?)", params[:category_ids]) if params[:category_ids].present?
query = query.where("npo_ids IN (?)", params[:npo_ids]) if params[:npo_ids].present?
#projects = query
I solved this. here's my code
def index
if params[:category_ids].present? || params[:npo_ids].present?
#conditions = {}
if params["category_ids"].present?
#conditions["categories"] = {:id => params["category_ids"].collect{|x| x.to_i}}
end
if params["npo_ids"].present?
#conditions["npo_id"] = params["npo_ids"].collect{|x| x.to_i}
end
#projects = Project.joins(:categories).where(#conditions)
else
basically it stored the .where conditions in #conditions, which looks something like this when there's both categories and npos:
{:categories => {:id => [1,2,3]}, :npo_id => [1,2,3]}
Then inserting this into
Project.joins(:categories).where(#conditions)
seems to work.
If you're filtering on a has_many relationship, you have to join. Then after joining, make sure to call the specific table you're referring to by doing something like this:
:categories => {:id => [1,2,3]}

rails 2.3 convert hash into mysql query

I'm trying to find out how rails converts a hash such as (This is an example please do not take this literally I threw something together to get the concept by I know this query is the same as User.find(1)):
{
:select => "users.*",
:conditions => "users.id = 1",
:order => "username"
}
Into:
SELECT users.* FROM users where users.id = 1 ORDER BY username
The closest thing I can find is ActiveRecord::Base#find_every
def find_every(options)
begin
case from = options[:from]
when Symbol
instantiate_collection(get(from, options[:params]))
when String
path = "#{from}#{query_string(options[:params])}"
instantiate_collection(format.decode(connection.get(path, headers).body) || [])
else
prefix_options, query_options = split_options(options[:params])
path = collection_path(prefix_options, query_options)
instantiate_collection( (format.decode(connection.get(path, headers).body) || []), prefix_options )
end
rescue ActiveResource::ResourceNotFound
# Swallowing ResourceNotFound exceptions and return nil - as per
# ActiveRecord.
nil
end
end
I'm unsure as to how to modify this to just return what the raw mysql statement would be.
So after a few hours of digging I came up with an answer although its not great.
class ActiveRecord::Base
def self._get_finder_options options
_get_construct_finder_sql(options)
end
private
def self._get_construct_finder_sql(options)
return (construct_finder_sql(options).inspect)
end
end
adding this as an extension gives you a publicly accessible method _get_finder_options which returns the raw sql statement.
In my case this is for a complex query to be wrapped as so
SELECT COUNT(*) as count FROM (INSERT_QUERY) as count_table
So that I could still use this with the will_paginate gem. This has only been tested in my current project so if you are trying to replicate please keep that in mind.

Dynamic conditions query in RoR

I'm trying to make query in RoR, but my conditions are coming from params and changing dynamically.
I've tried this:
#userlist = User.find(:all, conditions:{(name:params[:name] if params[:name] != nil), (lastname:params[:lastname] if params[:lastname] != nil)})
It's just my imagination, but shows what I mean.
thanx
If you're on Rails 3:
#userlist = User.scoped
#userlist = #userlist.where(name: params[:name]) if params[:name].present?
#userlist = #userlist.where(lastname: params[:lastname]) if params[:lastname].present?
etc..
you could do something like:
BlahController < ActiveController::Base
before_filter :find_params, :only => :index
def index
#user_list = User.where(#filtered_params).all
end
def find_params
#filtered_params = params[:name].present? ? "'name = ?', #{params[:name]}" : "'last_name = ?', #{params[:last_name]}"
end
end
So I assume you only have two conditions, a params[:name] or a params[:last_name]. If there are more, simply change the ternary to a if elsif statement.

Return records from 2 tables using mysql and rails 3

need help with this please:
#follows = Follow.where("admin_user_id = ?", session[:id])
This returns records from the Follow table, that has the following coloumns, :admin_user_id, :assignment_id. I would now like to do this:
#assignments = Assignment.where("id = ?", #follows.assignment_id)
The Asssignment table has the following columns, :id, :name.I have tried the "#follows.assignment_id" to substitute each id which i can then use in the view like,
<% #assignment.each do |assignment| %>
<%= assignment.name %>
<% end %>
Thanks in advance for your help
Part of the problem here is your first query: Follow.where(...) returns a scope, it will not perform the query until you try to access the #follows object. This is probably not a big deal, but you should probably make it this (unless you are going to dynamically add more conditions):
#follows = Follow.where("admin_user_id = ?", session[:id]).all
This ensures that #follows is an array of Follow objects. Because it's an array (and not a single Follow) there is no assignment_id on it. Change your second query to this:
#assignments = Assignment.where(:id => #follows.map{|f| f.assignment_id}).all
Basically, .map returns an array of the return values of the block instead of the original object it was called on, meaning instead of an array of follows, it returns an array of the assignment ids of each object. When you pass this array as the conditions, it generates a SQL query something like:
select * from assignments where id IN (1, 2, 3)
if your follows have assignment ids 1, 2, and 3.
In your model:
class Follow < ActiveRecord::Base
belongs_to :assignment
end
For Assignments
class Assignments < ActiveRecord::Base
has_many :follows
end
Then you can call
#assignments = []
#follows.collect {|f| #assignments << f.assignment}
Also:
This is the error i get:undefined method `assignment_id' for #<ActiveRecord::Relation:0xb6d8104c>
Make sure your sql table has a column called assignment_id with an integer value