Check whether there is no match in any row in SQL - sql

schedule = Session.select()
.join(Activity).join(Course)
.join(StuCouRel)
.join(Student)
.where(Student.id == current_user.id)
.join(StuActIgnore).where(Activity.id != StuActIgnore.activity)
Now, if StuActIgnore.activity has, say, three rows in this query, then it will have each session that 'gets through' output three times. It will compare each Session to every row in StuActIgnore.activity. I know what's going wrong; I just don't know how to fix it.
I want something like this:
schedule = Session.select()
.join(Activity).join(Course).join(StuCouRel).join(Student)
.where(Student.id == current_user.id)
.join(StuActIgnore)
.where(Activity.id not in StuActIgnore.activity)
that is; if Activity.id does not match for any StuActIgnore row, then the Session is added to the query. The code I wrote does not work because a ForeignKeyField is not iterable.
EDIT: I tried fixing it as follows:
schedule = Session.select()
.join(Activity)
.join(Course)
.join(StuCouRel)
.join(Student)
.where(Student.id == current_user.id)
.join(StuActIgnore)
.where(Activity not in current_user.ignoredactivities)
because this related_name ("ignoredactivities") is iterable, but this doesn't seem to work either.
EDIT2: I made it work by adding a separate for-loop. It works, but it's neither efficient nor elegant:
ignored = Activity.select().join(StuActIgnore).where(StuActIgnore.student == current_user.id)
for element in schedule:
if element.activity not in ignored:
classes.append(element)
Is there a more elegant way of doing the same thing?

Related

Rails order active record results based on one column and another if null

So I have an active record query that returns some records, lets say it looks like this.
jobs = Job.where(:user_id => current_user.id)
As you would expect this returns the current_user's jobs. Assume that the job has two dates, deadline_date and due_date. If I want to order on deadline_date I can do something like..
jobs.order("deadline_date asc")
That works as expected, now image I have something in the job model like this.
class Job < ActiveRecord::Base
def deadline_date
self.read_attribute(:deadline_date) || self.due_date
end
end
So the job will display its deadline_date if it is not nil else it will fallback to use the due_date. So to sort this I have done the following...
jobs.sort_by{|job| job.deadline_date}
jobs.sort_by{|job| job.deadline_date}.reverse
This solves my problem but I wondered it there were better alternatives, is it possible to achieve this using SQL? Also this produces some repeated code in that I have a sort_order variable in my controllers that I can pass directly like this...
jobs.order(sort_order)
Now it looks more like this...
if params[:sort] == "deadline_date"
if params[:order] == "asc"
jobs.sort_by{|job| job.deadline_date}
else
jobs.sort_by{|job| job.deadline_date}.reverse
end
else
jobs.order(sort_order)
end
Note: This is a arbitrary example in reality it is a bit messy but you get the idea. So I'm looking for an SQL alternative or a suggestion on how it could be improved. Cheers
If I understand you correctly, you should be able to do this using the COALESCE SQL function:
jobs.order(Arel.sql("COALESCE(deadline_date, due_date)"))
That's pretty much the same as deadline_date || due_date in Ruby.
I believe it to be a standard SQL thing, so it should work for most SQL dialects.

How do I search for keywords in rails?

I have a search form which works very well but I want to add keyword functionality to it. I'm not sure how. The search conditions look like this:
def search
conditions = {}
conditions[:targ_lang] = params[:targ_lang] unless params[:targ_lang].blank?
conditions[:inst_lang] = params[:inst_lang] unless params[:inst_lang].blank?
conditions[:start_level] = params[:start_level] unless params[:start_level].blank?
conditions[:end_level] = params[:end_level] unless params[:end_level].blank?
conditions[:skill] = params[:skill] unless params[:skill].blank?
conditions[:subject] = params[:subject] unless params[:subject].blank?
conditions[:inst_name] = params[:inst_name] unless params[:inst_name].blank?
conditions[:creator] = params[:creator] unless params[:creator].blank?
#conditions = Material.where("keywords like ?", "%#{keywords}") unless params[:keywords].blank?
#results = Material.find(:all, :conditions => conditions)
end
I've commented out the keyword line because it doesn't work at the moment. Obviously it's different to the others because we don't want to find an exact match, we want a single match from several possible keywords.
Can anyone help? Rookie question I know but I've been working on it for a while.

ruby on rails store sql result on a variable

Newbie here. I am trying to store the result of my search onto a variable.
#answer = q.answers.select(:name) which runs
"SELECT name FROM "answers" WHERE "answers"."question_id" = 1;" and returns
"t" for true.
It runs fine on the command line and shows the right result. But I want to compare that result to another variable.
How do i extract that result? #answer[0], or #answer, or answer_var = #answer[0]
i.e.
if #answer == some_other_variable OR
if #answer[0] == some_other_variable OR
if answer_var == some_other_variable
what value do #answer[0] and #answer[0] hold and how can I print the value to the log file? not the web page. I know it must be simple, but I can't get my head around it.
Thanks.
It's not really an answer to your question but...
If you want to follow "the rails way", you should better use Models and not deal with SQL at all.
E.g. :
#answer = q.answers.first # answers is an array, take the first
if #answer.name == ...
For the logging, I suggest you that : http://guides.rubyonrails.org/debugging_rails_applications.html#the-logger

LINQ Nested Query help

I'm trying to a LINQ query, and I have been stumped for some time. I tried looking up the documentation, and around here, but I can't quite seem to find enough pieces to make the whole thing.
If I were to be writing this in SQL, the query would be
SELECT *
FROM (Person JOIN Event ON Person.ID = Event.PersonID) as t
Where (Event.Type = "Invitation") AND !Exists(SELECT *
FROM Event
WHERE Event.Type = "Something"
AND Event.Conference = "someString"
AND t.ID = Event.PersonID)
Any input would be greatly appreciated, even if you only have a solution for part.
Your Event table appears to have a foreign key to Person. This seems unusual as it would imply that an Event can only have one person. I'm going to assume that your Event table is the many-many table in this model. Assuming you have an association between People and Events (PeopleEvents?), you should be able to do this with something like the following (using !Any in place of !Exists):
from person in People
from event in person.Events
where event.Type == "Invitation" &&
!person.Events.Any(event => event.Type == "Something" && event.Conference == "someString")
select new {person, event}
(note, you may want to project into some other structure here rather than projecting the select many I'm showing here.) If we had more information about your model or what you are trying to accomplish, we might be more help.

Array conditions for select on Active Record query

I want to be able to specify user specific conditions in a MAX() sql call in the :select portion of the active record query (Rails 2.3.12). Unfortunately the safe string interpolation doesn't seem to work for the :select condition. The code is below, is there any other way to manually ensure the incoming values are safe? (They should be as they're just id's but you can never be too sure.)
:select => ["`component_instances`.*, max(`users`.id = ? AND `permissions`.view = 1) AS user_view, max(`users`.id = ? AND `permissions`.edit = 1) AS user_edit", user.id]
The query is designed to indicate to me if a particular user has explicit permissions on a particular item in the site. It'll either return 1 (they do), 0 (they don't but others do), or nil (no one has explicit permissions).
Turns out you can manually use the sanitize_sql_array method to do this:
:select => sanitize_sql_array(["`component_instances`.*, max(`users`.id = ? AND `permissions`.view = 1) AS user_view, max(`users`.id = ? AND `permissions`.edit = 1) AS user_edit", user.id, user.id])