Checking if a boolean column is true in MySQL/Rails - mysql

Rails and MySQL:
I have a table with several boolean columns representing tags. I want to find all the rows for which a specific one of these columns is 'true' (or I guess in the case of MySQL, '1'). I have the following code in my view.
#tag = params[:tag]
#supplies = Supply.find(:all,
:conditions=>["? IS NOT NULL and ? !=''", #tag, #tag], :order=>'name')
The #tag is being passed in from the url. Why is it then that I am instead getting all of my #supplies (i.e. every row) rather than just those that are true for the column for #tag.
Thanks!

If params[:tag] is set to foo, the find method is generating this query:
select * from supplies where 'foo' is not null and 'foo' != '' order by name;
This is returning all your Supply records because both conditions are always true.
'foo' is not null
'foo' != ''
Of course you're intending for params[:tag] to be a column name, but that is just terrible design.
You should have a tag attribute on your Supply model and use the following finder:
#supplies = Supply.all(:conditions => ["tag = ?", params[:tag]], :order => "name")
If you really want the ability for Supplies to have the option for multiple Tags, use:
class Supply < ActiveRecord::Base
has_and_belongs_to_many :tags
end
class Tag < ActiveRecord::Base
has_and_belongs_to_many :supplies
end
#supplies = Supplies.all(:conditions => {:tags => ['foo', 'bar']}, :order => "name")

I think this is what you want to do
#tag = params[:tag]
#supplies = Supply.find(:all, :conditions=>["? = ?", #tag, true], :order=>'name')

Related

MYSQL Query within Rails

Need to update a field within my mysql db. Would like to use the following query within rails:
update users set exported = TRUE where id = #{name[12]}
Currently, have the following:
db = Mysql2::Client.new( :host => 'localhost', :username => 'username', :password => 'password', :database => 'database')
results = db.query("select * from users where start_date is not NULL AND exported = 0").each(:as => :array)
results.each do |name|
db.query("update users set exported = TRUE where id = #{name[12]}")
end
index 12 is equal to the UID.
I would suggest that you use ActiveRecord for database calls when you are using Ruby on Rails.
I assume that you have at least a basic User model like this:
class User < ApplicationRecord
end
With an User model like that your query could look like this:
User.where.not(start_date: nil).where(exported: false).update_all(exported: true)
If you're using rails, I'd suggest using ActiveRecord. Your update will be:
#users = User.find(:all, :where => 'start_date is not null and exported = 0 and id = ?', name[12])
#users.each{ |user|
user.exported = true
user.save!
}
Hope that helps! Leave a comment if you need further help.

Rails Sorting on a value coming from two columns

I have two tables, A and B. A and B have a foreign key. Both ActiveRecord.
class A
has_one :b
def valueRendered
b.value1 || b.value2
end
end
class B
( belongs_to :a, :foreign_key => :keyb ) if self.b
end
Here the value coming from valueRendered method in A is having values from field value2 of B when value1 is null. I have to sort the table using the valueRendered, i.e., table should be sorted on the basis of values of both value1 and value2. How to proceed?
Edit:
To be more specific, suppose there is one calculated column (a method in rails) which has value from field "value1" but if value1 is null, the value comes from "value2". I want to sort the whole table (not limited to any specific no of records or scope) with respect to this calculated field (method). I am confused how to proceed.
Some more edit: Actual sample code
In the controller,
sort_fields = ['offer_orders.id','offers.name','offer_orders.created_at',
'offer_orders.country', 'offer_orders.ip_address',
'fraud_score_daily.adjusted_fraud_probability, fraud_score_daily.fraud_probability',
'players.email','players.account_status',
nil,
nil,
nil,
nil
]
arel = OfferOrder.includes(:offer, :player, :fraud_score_daily).group('fraud_score_daily.offer_order_id').order('dt desc')
arel = paginate_table_data(arel, :sort_fields => sort_fields)
paginate_table_data method is in a helper
def paginate_table_data(arel, opts={})
opts.assert_keys(:required => [:sort_fields])
#page_size = page_size
#current_page = current_page
arel.paginate(:page => #current_page, :per_page => params[:iDisplayLength]).
order(order_by(opts[:sort_fields]).join(', '))
end
How about something like:
scope :order_by_value_rendered, joins(:b).order("value1, value2")

Rails Query for best way to select the most recent record

I have this method which I want me to fetch the most recent activity_id for the corresponding user_id from the model UserActivity that keeps track of all the user activities and from that get the description of the activity_id from another model Activity.
The function works fine but at times throws bugs as "Not able to find activity_id". May be there could be a better way to implement this or Am I doing something wrong here ?
def last_activity(date, user_id)
active_id = UserActivity.find(:all, :conditions => ["Date(updated_at) <= ? and user_id = ?", date, user_id]).last.activity_id
text = Activity.find(active_id).description
end
The Schema of the model UserActivity is as follows :
Please help me get this fixed. Thanks !!
Ruby version 1.8.7, Rails 2.1.2
Assuming you have following models
class User
has_many :user_actvities
has_many :activities, :through => :user_actvities,
:order => "user_actvities.id"
end
class UserActivity
belongs_to :user
belongs_to :activity
end
class Actvity
has_many :user_actvities
has_many :users, :through => :user_actvities
end
To get the current user's last activity
current_user.activities.last
This relies on the fact that UserActivity object with the max id is the latest activity.
If you update the UserActivity after creation, you have to change the order clause of the association, i.e.
has_many :activities, :through => :user_actvities,
:order => "user_actvities.updated_at"
Either the query is not finding any match or some records might be having null values for activity_id column, following code should work
user_activity = UserActivity.find(
:all, :conditions => ["DATE(updated_at) <= ? AND user_id = ? AND activity_id IS NOT NULL", date, user_id],
:order => "updated_at DESC", :limit => 1).first
text = Activity.find(user_activity.active_id).description rescue nil

Alternative as NOT IN gives a blank array

I have a query in my rails application,
user_info = Information.where("user_id = ? and department_id NOT IN (?)",user.id, Department.unapproved_departments ).all(:include => [:name, :project]).
Here unapproved_departments contains an array of ids in Department table.
The problem arises when unapproved_departments is a blank array.In those cases "NOT IN"
checks for ids present in the array and entire user_info is returned as a blank array.
So i would like to have all the data with ids other than those in unapproved_departments array or you can say an alternative for NOT IN
Thanx
Theres nothing wrong with NOT IN -- just that you don't want it to fire when there's nothing there.
I suggest:
user_info = Information.where("user_id = ?", user)
unapproved_departments = Department.unapproved_departments
if unapproved_departments.present? # true if not blank or nil
user_info = user_info.where("department_id NOT IN (?)", unaproved_departments)
end
user_info.all(:include => [:name, :project])
As you can see, you can chain the conditions together.
Can't you just have a special case for when unapproved_departments is empty?
if Department.unapproved_departments.empty?
user_info = Information.where("user_id = ?",user.id).all(:include => [:name, :project])
else
user_info = Information.where("user_id = ? and department_id NOT IN (?)",user.id, Department.unapproved_departments ).all(:include => [:name, :project])
end
it will be better if you define better unapproved_departments to retun [nil] instead of []
Oterwhise you can add [0] to your code :
user_info = Information.where("user_id = ? and department_id NOT IN (?)",user.id, (Department.unapproved_departments << 0) ).all(:include => [:name, :project]).
If we concentrate just on the "NOT IN" part:
user_info = Information.where("department_id NOT IN (?)", []).to_sql
# => SELECT `informations`.* from `informations` where department_id not in (NULL)
Which is weird because of null-tests: http://dev.mysql.com/doc/refman/5.0/en/working-with-null.html
What we can do is reverse the test and get the required result:
user_info = Information.where("NOT (department_id IN (?))", []).to_sql
# => SELECT `informations`.* from `informations` where NOT (department_id in (NULL))
It works because in MySQL everything is != NULL (and also < NULL and > NULL at same time!).

How do I select a specific record from Many-to-many relationships which does not contain a specific item in Rails 2?

I am stuck with this for a couple of hours. It could be a quick solution but my brain is overheated now. Ok here it is.
I have Session and SessionType models which have many-to-many relationships to each other as follows.
class Session < ActiveRecord::Base
...
has_and_belongs_to_many :session_types
...
end
class SessionType < ActiveRecord::Base
...
has_and_belongs_to_many :sessions
...
end
What I want is to get a session which doesn't contain any specific session_type, eg.,
Session.find(:all, :joins => [:session_types], :conditions => ["session_types.id <> 44"])
It doesn't work for me since the above query will still give me the sessions which have session_types.id "44" in many of its associations because of the nature of many-to-many relationships.
Also the following mysql code doesn't work as well.
select sessions.* from sessions
INNER JOIN `session_types_sessions` ON `session_types_sessions`.session_id = `sessions`.id
WHERE ( session_types_sessions.session_type_id NOT IN (44))
GROUP BY sessions.id
Any help will be appreciated.
Thanks.
First select those sessions which are of type 44:
session_types_44 = Session.find(:all, :joins => :session_types,
:conditions => { :"session_types.id" => 44 }).uniq
and select sessions which do not fall into the above:
sessions_without_type_44 = Session.find(:all,
:conditions => "id NOT IN (#{session_types_44.join(",")})")
You need to be careful with that because if session_types_44 is empty array you will get SQL error.
And to answer your second question:
do you know how I could change the SQL to filter like "get me sessions which have session_type_id '43', but they must NOT have '44'
Take the result from sessions_without_type_44 and use it. First select SessionType with 43 and through association get all sessions which belong to that SessionType and their ids are within the sessions_without_type_44:
SessionType.find(43).sessions.all(:conditions => {
:id => sessions_without_type_44 })
Try this:
SELECT sessions.*
FROM sessions
LEFT JOIN session_types_sessions ON session_types_sessions.session_id = sessions.id AND session_types_sessions.session_type_id = 44
WHERE session_types_sessions.session_id IS NULL
Try this:
Session.all(
:include => :session_types,
:conditions => ["session_types.id IS NOT NULL AND session_types.id != ?", 44])
)
The include option uses LEFT JOIN hence this query will work.