Могу ли я рассчитывать на основе виртуального атрибута? - PullRequest
0 голосов
/ 18 августа 2010

У меня следующая ошибка:

no such column: company_name: SELECT count("contact_emails".id) AS count_id FROM "contact_emails" 

Модель ContactEmail НЕ имеет столбца company_name. Я создал его как виртуальный атрибут.

Невозможно сделать выбор на основе этой информации? Как мне тогда это сделать?

ContactEmail принадлежит_ к контакту, который принадлежит_ компании.

1 Ответ

0 голосов
/ 18 августа 2010

Виртуальные атрибуты, добавленные в определение класса, но отсутствующие в базе данных, не могут использоваться для выбора базы данных, поскольку виртуальный атрибут отсутствует в базе данных.

Вы можете использовать базу данных, чтобы выбрать расширенный набор нужных строк, а затем сделать второй выбор на уровне Rails, который будет использовать виртуальный атрибут.

Например

# model Citizen class file
# model fields:
#   id
#   name
#   age
#   city

def can_vote?  # a virtual attribute
   age >= 18 
end

def self.find_voters_by_city(city)  # class level finder
   # returns array of voters in a city
   citizens = Citizen.find_by_city(city) # First select done in database
   citizens.select{|citizen| citizen.can_vote?} # Second select is done at Rails
                                                # level using the Array#select
                                                # method
end

Обратите внимание, что хотя вышеперечисленное работает нормально, вы должны быть очень осторожны в отношении проблем с производительностью. Выбор на уровне Rails намного медленнее, чем выбор в БД. Кроме того, вы передаете гораздо больше данных через соединение Rails / СУБД, чем было бы необходимо в противном случае.

Если вы собираетесь что-то выбирать на регулярной основе, то обычно лучше поместить виртуальный атрибут в базу данных - сделать его реальным атрибутом в базе данных.

Если ваша таблица не может быть изменена, вы также можете создать вторую таблицу с отношением has_one. Вторая таблица будет содержать дополнительные атрибуты.

Добавлено: выбор в базе данных по двум таблицам

### model Contact
#   id
#   name
#   city
has_one :company
def company_name; company.name; end # a virtual attribute

### model Company
#   id
#   contact_id
#   name
#   employee_count
belongs_to :contact

### Selecting on city (from Contact) and employee_count (from Company)
city = xyz # the city we are searching for
employee_count = 123 # minimum company size we want
contacts = Contact.find(:all, 
      :conditions => ["contacts.city = ? and companies.employee_count >= ?",
         city, employee_count],
      :include => :company)

# above statement does the join and select in the database
# There are also techniques involving named scopes for the above
# And in Rails 3, it will be different too.
...