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")
Related
Is there a way to get the Distinct values from each column in a MYSQL database without having to do multple SELECT DISTINCT statements for each column?
Right now in my rails controller I'm using .pluck() to run:
#first = User.distinct.pluck(:first_name)
#last = User.distinct.pluck(:last_name)
#city = User.distinct.pluck(:city)
#state = User.distinct.pluck(:state)
#age = User.distinct.pluck(:age)
#info = {
'first' => #first,
'last' => #last,
'city' => #city,
'state' => #state,
'age' => #age
}
respond_with #info
Which creates an object with my two unique arrays in it, however it takes about 7.7 seconds (my table has 3.2 million fully-populated rows) and runs two separate SQL queries.
I tried this method, but this is giving me an array of each unique COMBINATION:
#info = User.distinct.select(:first_name, :last_name, :city, :state, :age)
respond_with #info
Not sure how you want your final data to be output, but if you want to avoid multiple SQL statements, you can do something like this:
SELECT
ARRAY(SELECT DISTINCT(col1) FROM MyTable) AS col1_values,
ARRAY(SELECT DISTINCT(col2) FROM MyTable) AS col2_values
This will give you a single row with all the DISTINCT values for each "colX" you specify. Just add on whatever additional columns you want to include. The DISTINCT values in each column will be returned as an array.
Performance will still be stinky, since I don't think you can avoid doing multiple distinct DISTINCT operations.
Let me know if that's what you're looking for.
You could do this:
#info = User.distinct.select(:first_name, :last_name, :city, :state, :age)
#first, #last, #city, #state, #age = [], [], [], [], []
#info.map{ |i| #first<<i[0]; #last<<i[1]; #city<<i[2]; #state<<i[3], #age<<i[4] }
#info = { 'first' => #first,
'last' => #last,
'city' => #city,
'state' => #state,
'age' => #age }
respond_with #info
Please try benchmarking before implementing this in production.
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
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!).
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.
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')