Как объединить два активных результата записи, чтобы получить новый результат, который можно затем отфильтровать? - PullRequest
3 голосов
/ 16 сентября 2011

Представьте себе сценарий ...

#models/user.rb
class User < ActiveRecord::Base
    has_many :accounts, :conditions => { :active => 1 }
end

#models/account.rb
class Account < ActiveRecord::Base
    belongs_to :user

    def public_accounts
        Account.all :conditions => { public => true }
    end
end

Теперь представьте, что я хочу объединить User (: id) .accounts с Account.public_accounts, чтобы показать список всех учетных записей, доступных пользователю.

Так что вы думаете, что я смогу обновить модель User, чтобы она выглядела следующим образом.

#models/user.rb
class User < ActiveRecord::Base
    has_many :accounts, :conditions => { :active => 1 }

    def all_accounts
        self.accounts + Account.public
    end
end

Однако теперь я не смогу использовать метод all (), поскольку он больше не относится к объекту такого типа.

В контроллере я хотел бы сделать это ...

#controllers/accounts_controller.rb
def search_all
    User.find(params[:user_id]).all_accounts.all(
        :offset => params[:offset],
        :limit => params[:limit]
    )
end

Мысли

Обновление № 1: Сфера не будет работать для моего сценария. Я упростил свой сценарий, чтобы попытаться донести свою точку зрения. Как уже говорилось, мне нужен способ объединить два активных результата записи и сохранить возможность их дальнейшей фильтрации в моем контроллере.

Итак, вопрос в том, почему? Причина в том, что я пытаюсь объединить два набора записей в единую коллекцию, а одна из коллекций вообще не связана с пользователем.

Я реорганизовал приведенный выше сценарий, чтобы попытаться показать более точный пример, не усложняя его.

Ответы [ 4 ]

4 голосов
/ 16 сентября 2011

Это может быть хорошим сценарием для использования областей .

Вы можете определить активные и неактивные области в модели Учетной записи, а затем использовать следующее:

User.accounts
User.accounts.active
User.accounts.inactive

Вы можете даже объединять области в цепочку, чтобы вы могли сделать что-то вроде:

User.accounts.active.paid_up
2 голосов
/ 16 сентября 2011

ответ jklina правильный, в этой ситуации лучше всего использовать области.Области видимости содержат сахаристый синтаксис и более читабельны.Я подробно остановлюсь на настройке:

class User < AR::Base
  has_many :accounts
end

class Account < AR::Base
  belongs_to :user

  scope :active, where(:active => true)
  scope :inactive, where(:active => false)
end

Затем вы получите доступ к областям учетной записи, как показал jklina: User.find(1).accounts.active и т. Д. Доступ ко всем учетным записям пользователя, например: User.find(1).accounts.

ОБНОВЛЕНИЕ:

Я исправил некоторые ошибки и добавил еще несколько ниже.

Исходя из обновлений вашего вопроса, я думаю, вам нужно сделать метод public методом для класса:

class Accounts < AR::Base
  ...
  # This is essentially a scope anyways
  def self.public
    where(:public => true)
  end
end

class User < AR::Base
  ...
  # This should return all the users accounts
  # and any public accounts
  def all_accounts
    Account.where("user_id = ? OR public is true", self.id)
  end
end
0 голосов
/ 16 сентября 2011

Вы пытаетесь получить доступ к двум отдельным таблицам и применить к ним LIMIT / OFFSET как объединенное объединение. Это не произойдет, если вы не объедините их логически на уровне SQL, а не на уровне ActiveRecord.

Похоже на написание SQL, возможно, использование UNION, а затем find_by_sql может быть вашим лучшим.

0 голосов
/ 16 сентября 2011

Давайте посмотрим на возвращаемые значения в цепочке:

User.find(params[:user_id]) # returns an instance of User class
User.find(params[:user_id]).all_accounts # returns an array

В классе Array нет метода экземпляра с именем all, поэтому вы видите эту ошибку.Это не ошибка.

Почему бы вам не попробовать это:

class User
  has_many :accounts, :conditions => { :active => 1 }
  has_many :all_accounts :conditions => ["(active = ? OR public = ?)", 
                           true, true]
end

Теперь вы можете:

User.find(params[:user_id]).all_accounts.all(:limit => 10, :offset => 2)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...