Find first two records from collection - ruby-on-rails

I want to retrieve the first two records from collection such that, collection is like:
#collect_firstnames = #name.firstnames
From this collection I want to fetch first two records...
I used limit it is not working, :limit => 2

I take it that #name.firstnames is a has_many relationship. You need to pass the options to all:
#name.firstnames.all(:limit => 2)

You can use the :limit option like this:
#first_two = Name.find(:all, :limit => 2)
Edit
It's the same idea, assuming firstnames is a relationship (just like Swanand said below)
#first_two = #name.firstnames.all(:limit => 2)

Related

Filter activerecord by nested ID and value combination in Ruby on Rails

Lets say I have two models with a many to many relationship: Item and Property
Now I have an array of properties and I want to filter all items which properties match a given value (lets say a boolean value: property.value = true)
When I try
#items = Item.includes(:properties).where(:properties => {:id => [1,2,3].to_a, :value => true})
I would like to get all items where property(1) is true AND property(2) is true and so on. But with the code above I get all items related to the property id's and where any property is true. How should I change my code?
I would appreciate not to use a gem for this.
Looks like you are almost there:
property_ids = [1,2,3]
Item.joins(:properties).
where(:properties => { :id => property_ids, :value => true }).
group('items.id').
having('COUNT(properties.id) >= ?', property_ids.size)
joins does an INNER JOIN and is preferred over includes when you really need to join tables.
where is basically the conditions you already had, the only change is that there is not need to call to_a on the array.
Than you have to group to make that COUNT in SQL work.
having extracts the lines that have at least the expected number of property lines matching the condition.

Querying based on two associated records

I have a product that has many variants, those variants have two attributes: Size and Color.
I want to query for the Variant based on the two attributes I pass in - I got it to work with following:
variants = Spree::Variant.joins(:option_values).where(:spree_option_values => {:id => size.id}, :product_id => prod.id).joins(:option_values)
variant = variants.select{|v| v.option_values.include?(size)}
From my understanding, the select method more or less iterates through the array, which is kinda slow. I would rather have a query that finds the variant directly based on those two attributes.
I tried the following:
Spree::Variant.joins(:option_values).where(:spree_option_values => {:id => size.id}, :product_id => prod.id).joins(:option_values).where(:spree_option_values => {:id => color.id})
but this only ended up in returning an empty array.
How would I go about this?
Edit: Here are the product, variant and option_values models:
Product:
https://github.com/spree/spree/blob/master/core/app/models/spree/product.rb
Variant:
https://github.com/spree/spree/blob/master/core/app/models/spree/variant.rb
OptionValue: https://github.com/spree/spree/blob/master/core/app/models/spree/option_value.rb
OptionType: https://github.com/spree/spree/blob/master/core/app/models/spree/option_type.rb
Updated 2: you're right, this is not what you looking for.
So you can:
1) Build SQL subquery: (if joined table has size and has color at the same time then return TRUE). How quick it will be working - is a question...
2) Imagine you've created a model "ValuesVariants" for table "spree_option_values_variants" and kicked out habtm (replace with 2 has_manys + 2 has_manys through). Now you can search ValuesVariants with (option_type_id = size_id||color_id AND variant_id IN (array of product's variant ids)), extracting matched variants. It can be quick enough...
3) You can use :includes. so associated objects loaded into the memory and the second search do by array methods. In this case the concern is in memory usage.

unable to determine row count Ruby-On-Rails

im trying to build a cart in ruby on rails it requires me to show the output like this : You have 3 items in your cart (3 being the number of items in my cart) and im trying to find the number of rows in the table line_items where the cart_id is 5.
#line_items.find(:all, :condition => { :cart_id => "5"}).count
if anyone know how i should write this, please let me know.. Thanks in advance
You can do it the slow way:
YourModelClass.find(:all, :conditions => { :card_id => 5 }).count
or the fast way:
YourModelClass.count(:conditions => { :card_id => 5 })
The fast way simply does a COUNT(*) inside the database, the slow way pulls the whole result set out of the database, turns it into objects, and then counts them.
There's also the modern Rails3+ way:
YourModelClass.where(:card_id => 5).count
That does a select count(*) from t where card_id = 5 inside the database. Don't use this one though:
YourModelClass.count(:card_id => 5)
That will do a select count(card_id = 5) from t and that's nothing at all like what you want.
it should be something alone the line of
LineItem.count(:conditions => {:cart_id => 5})
since i don't really know what's the model name, and the association... hope this helps =)

Is it possible to delete_all with inner join conditions?

I need to delete a lot of records at once and I need to do so based on a condition in another model that is related by a "belongs_to" relationship. I know I can loop through each checking for the condition, but this takes forever with my large record set because for each "belongs_to" it makes a separate query.
Here is an example. I have a "Product" model that "belongs_to" an "Artist" and lets say that artist has a property "is_disabled".
If I want to delete all products that belong to disabled artists, I would like to be able to do something like:
Product.delete_all(:joins => :artist, :conditions => ["artists.is_disabled = ?", true])
Is this possible? I have done this directly in SQL before, but not sure if it is possible to do through rails.
The problem is that delete_all discards all the join information (and rightly so). What you want to do is capture that as an inner select.
If you're using Rails 3 you can create a scope that will give you what you want:
class Product < ActiveRecord::Base
scope :with_disabled_artist, lambda {
where("product_id IN (#{select("product_id").joins(:artist).where("artist.is_disabled = TRUE").to_sql})")
}
end
You query call then becomes
Product.with_disabled_artist.delete_all
You can also use the same query inline but that's not very elegant (or self-documenting):
Product.where("product_id IN (#{Product.select("product_id").joins(:artist).where("artist.is_disabled = TRUE").to_sql})").delete_all
In Rails 4 (I tested on 4.2) you can almost do how OP originally wanted
Application.joins(:vacancy).where(vacancies: {status: 'draft'}).delete_all
will give
DELETE FROM `applications` WHERE `applications`.`id` IN (SELECT id FROM (SELECT `applications`.`id` FROM `applications` INNER JOIN `vacancies` ON `vacancies`.`id` = `applications`.`vacancy_id` WHERE `vacancies`.`status` = 'draft') __active_record_temp)
If you are using Rails 2 you can't do the above. An alternative is to use a joins clause in a find method and call delete on each item.
TellerLocationWidget.find(:all, :joins => [:widget, :teller_location],
:conditions => {:widgets => {:alt_id => params['alt_id']},
:retailer_locations => {:id => #teller_location.id}}).each do |loc|
loc.delete
end

Top 3 records ordered by a field in rails

In ruby on rails how do I find the top 3 records of my table called notices ordered by a particular field, in my case I want to order by the position field which is an integer.
So my notices table looks like this:
Any help would be greatly appreciated.
Considering you have Notice ActiveRecord class, this should do:
Notice.find(:all, :limit => 3, :order => 'particularField')
You'd do something like:
Notice.find(:all,:order => "position", :limit => 3)
That would bring the 3 first records ordered by position (in this example, positions 1,2,3 or the first lesser ones. You can change the order value to "position DESC" if you want positions 20,19,18, for example).
Good luck!

Resources