I have a rails query that I would like to run. The only problem that I am having is the query structure.
Essentially the query looks like this
queryList = model.find(:all, :conditions => [id = "id"])
#returns a query list
#here is the issue
compound = otherModel.find(:first, :select => "an_id",
:conditions => ["some_other_id=? and an_id=?, some_other_id, an_id])
Where an_id is actually a list of ids in the query list. How can I write that in rails to basically associate a single id to a list that may contain ids...
If you use a hash as conditions, the operation is an AND.
obj = Model.first(:conditions => {:field1 => "val1", :field2 => "val2"})
Related
Is it possible to make a Model query in rails with an include statement, but to have the "include" only if another condition occurs?
I have this code:
#families = Family.find(:all,
:conditions => family_conditions,
:select => 'families.id,families.name',
:include => families_include_array)
So the include should be there only if the families_include_array is not null.
You should add your query in an if statement
if families_include_array.is_nil?
#families = Family.find(:all,:conditions => family_conditions, :select => 'families.id,families.name')
else
#families = Family.find(:all,:conditions => family_conditions, :select => 'families.id,families.name', :include => families_include_array)
end
Or you can create your SQL request as string and send it to SQL with ActiveRecord::Base.connection.execute
UPDATE
Or you can try to override the find method
def self.find(*args)
records = super
# Manipulate records
end
I'm trying to do something along the following lines:
if start_date?
query = where("datetime > :start_date", :start_date => start_date)
end
if end_date?
query = where("datetime <= :end_date", :end_date => end_date)
end
if client
query = where("client.name LIKE :client", :client => client)
end
if staff
query = where("staff.name LIKE :staff", :staff => staff)
end
paginate :per_page => 20, :page => page,
:conditions => query,
:order => 'datetime'
I can't find any examples though of how to build up a query and use it along with paginate plugin. Of course the query isn't correct yet as I've got to figure out how to do the joins so I can query against the other properties in other tables, but other than that, how do you build up queries to use in the conditions?
You want to put the .paginate call on the end of the chain of where calls, like this (all one line, split up for readability)
SomeClass.where("datetime > :start_date", :start_date=>start_date).
where("datetime < :end_date", :end_date=>end_date).
paginate(:per_page=>20,:page=>page)
If you want to conditionally add the conditions, you can do that too, like:
x = SomeClass
x = x.where("datetime > :start_date", :start_date=>start_date) if start_date
x = x.where("datetime < :end_date", :end_date=>end_date) if end_date
x.paginate(:per_page=>20,:page=>page)
You can try this if you installed kaminari gem :
ModelName.where( your_query ).page(params[:page]).per(50)
.where() returns ActiveRecord::Relation
.paginate()'s :conditions parameter has to be an array of conditions as if it was an argument of .where().
You should fix your code as next:
if start_date?
query = ["datetime > :start_date", :start_date => start_date]
end
etc.
ActiveRecord Relation doesn't have paginate method
I am using Rails 2.3.5 and is wondering if it is possible to rewrite this query using conditions as a hash.
joined_deals = Deal.all :joins => :shops
:conditions => ["shops.name = ?", name]
to something like :conditions => {"shops.name" => name}. Is it possible in Rails 2?
Yes, it is possible in Rails 2.
For more information, refer here:
specifying-conditions-on-the-joined-tables
In my application, Annotations are considered "accepted" if either:
They have been explicitly marked "accepted" (i.e., their state == 'accepted')
They were last updated by a user who has the "editor" role
My question is how to find all accepted explanations with a single DB query. Basically I'm looking for the database-driven version of
Annotation.all.select do |a|
a.last_updated_by.roles.map(&:name).include?('editor') or a.state == 'accepted'
end
My first attempt was
Annotation.all(:joins => {:last_updated_by => :roles}, :conditions => ['roles.name = ? or annotations.state = ?', 'editor', 'accepted'])
But this returns a bunch of duplicate records (adding a .uniq makes it work though)
Changing :joins to :include works, but this makes the query way too slow
Are the results of your first attempt just wrong or do they only need an ".uniq"?
Have you tried
:include => {:last_updated_by => [:roles]}
instead of the join?
or making two queries
#ids = Editor.all(:conditions => ["role = 'editor'"], :select => ["id"]).map{|e|e.id}
Annotation.all(:conditions => ["last_updated_by in (?) or state = ?", #ids.join(","), "accepted"]
is that any faster?
I have a fairly large model and I want to retrieve only a select set of fields for each record in order to keep the JSON string I am building small.
Using :select with find works great but my key goal is to use conditional logic with an associated model. Is the only way to do this really with a lamda in a named scope? I'm dreading that perhaps unnecessarily but I'd like to understand if there is a way to make the :select work with a condition.
This works:
#sites = Site.find :all, :select => 'id,foo,bar'
When I try this:
#sites = Site.find :all, :select => 'id,foo,bar', :include => [:relatedmodel],
:conditions => ["relatedmodel.type in (?)", params[:filters]]
The condition works but each record includes all of the Site attributes which makes my JSON string way way too large.
Thanks for any pointers!
The to_json call supports :except and :only options to exclude/include model fields during serialization.
#sites.to_json(:only => [:name, :foo, :bar])
Call above serializes the Site objects with fields name and location.
#sites.to_json(:only => [:name, :location],
:include => { :relatedmodel => {
:only => [:description]
}
}
)
Call above serializes the Site objects with fields name, and location and contained RelatedModel objects with description field.