我可以根据虚拟属性进行统计吗?

时间:2010-08-17 23:49:08

标签: sql ruby-on-rails virtual-attribute

我有以下错误:

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

模型ContactEmail没有列company_name。我将其创建为虚拟属性。

根据该信息进行选择是不可能的?那怎么办呢?

ContactEmail belongs_to contact_to Company的联系方式。

1 个答案:

答案 0 :(得分:0)

添加到类定义但不存在于数据库中的虚拟属性不能用于数据库选择,因为虚拟属性不在数据库中。

您可以使用数据库选择所需行的超集,然后在将使用虚拟属性的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级别选择要比在dbms中选择要慢得多。此外,您通过Rails / DBMS连接传输的数据远远多于其他所需的数据。

如果您要定期选择某些内容,那么通常最好将虚拟属性推送到数据库中 - 使其成为数据库中的真实属性。

如果无法更改表,您还可以创建具有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.