views:

48

answers:

3

Hi!

My model looks like this (example):

class Bank < ActiveRecord::Base
  has_and_belongs_to_many :currencies
  # other stuff
end

When I want to get some bank from database i do:

bank = Bank.first :joins => :some_table,
         :conditions => {
           #some conditions
         }

Now, is there any way to explicitly retrieve currencies from database for provided conditions and sort them in some order and store them in bank.currencies ?

I'm doing something like this:

bank.currencies.reject! { |c| c.value < something }
bank.currencies.sort! { |x,y| x.value <=> y.value }

It works but this way I retrieve all records and filter them by myself. I would like to have DBMS do it for me.

This is just an example with banks and currencies. I have some big records and I think it is important just to retrieve those which interest me.

+1  A: 

Maybe this helps you?

bank = Bank.first
concurrencies = Concurrency.find(:all, :conditions => {:bank => bank}, :order => "position desc")

Or you could change your bank model

def Bank << AR
  has_many :concurrencies

  def ordered_concurrencies
    Concurrency.for_bank(self)
  end
end

def Concurrency << AR
  belongs_to :bank

  named_scope :for_bank, lambda { |*args| {:conditions => {:bank => args.first}, :order => "position desc"} }
end

So you could call

Bank.first.ordered_concurrencies

and get the ordered concurrencies as ActiveRecord-Collection.

Beside this, with this solution you can add other conditions as well:

Bank.first.ordered_concurrencies.find(:all, :conditions => ["name like ?", "Dollar"])
Lichtamberg
+1  A: 

You can issue "find" clauses on the relationship, like this:

bank.currencies.find(:all, :conditions => {something}, :order => {something})

or, if you prefer:

bank.currencies.all(:conditions => {something}, :order => {something})

All the standard ActiveRecord options should be available - e.g. limit, order etc.

Of course, if you find yourself re-using the query logic, you can declare named scopes on the Currency model - say, 'with_count_greater_than' and 'in_order' - and then chain them together:

bank.currencies.with_count_greater_than(10).in_order

You may also want to investigate SearchLogic, which implements many useful named scopes for you.

NeilS
A: 

I was hoping for some build-in behavior.

I think I get the whole idea. But what should I do not to have ActiveRecord executing this query every time i refer to bank.currencies

Can I do something like this in Bank model

def currencies
  if @currencies.nil?
    @currencies = Currency.all :conditions => {something}, :order => {something})
  end
  return @currencies
end
Kylo
That should, I believe, be dealt with by Rails' query caching mechanism, which won't resend the query to the database if identical queries are made in the same request. Does the query show up as [CACHED] in your log file?
NeilS
Oh, and if you do write code like that in your model, writing simply 'currencies' (i.e. self.currencies) would be a simpler way of writing 'Currency.find(:all, :joins => {something}, :conditions => {something})'. It's some handy magic that the has_and_belongs_to_many sets up for you.
NeilS