0

我正在使用设计进行身份验证,并且对我的用户与他们可以登录的子域相关联的方式感到困惑。我研究了 plataformatec 提供的信息以及 Dave Kenedy 在 Ruby Source 上的精彩文章。不过,我仍然不太了解连接和查询,无法很好地完成这项工作。

class User < ActiveRecord::Base
  has_many :residences
  ...
end

class Residence < ActiveRecord::Base
  belongs_to :user
  belongs_to :apartment
  ...
end

class Apartment < ActiveRecord::Base
  has_many :residences
  belongs_to :building
  ...
end

class Building < ActiveRecord::Base
  attr_accessible :subdomain
  has_many :apartments
  ...
end

config/initializers/devise.rb我添加了:

config.request_keys = [:subdomain]

app/models/user.rb我已将默认设计方法 `self.find_for_authentication 替换为:

def self.find_for_authentication(conditions={})
  conditions[:residences] = { :subdomain => conditions.delete(:subdomain) }
  find(:first, :conditions => conditions, :joins => :residences)
end

当我运行我的规范时,我收到以下错误:

PG::Error: ERROR:  column residences.subdomain does not exist

我知道我必须以某种方式将我的residence表一直加入到building表中,以确认登录的用户隶属于具有正确子域的建筑物,但我不知道该怎么做。有人有想法么?Rails Docs有关于加入表格的信息,但这也让我感到困惑。(关于数据库和连接表的基本信息也会有所帮助。;-))

更新

我在 app/models/user.rb 中修改过

def self.find_for_authentication(conditions={})
  subdomain = conditions.delete(:subdomain)
  building = Building.find_by_subdomain(subdomain)
  apartments = Apartment.where('apartment.building_id' => building.id)
  conditions[:residences] = { :apartment_id  => apartments }
  find(:first, :conditions => conditions, :joins => :residences)
end

这可能更接近我需要的,但我仍然在 rspec 中收到以下错误:

1) UserSubdomainLogins signin should not be able to signin to building without access 
 Failure/Error: click_button "Sign in"
 ActiveRecord::StatementInvalid:
   PG::Error: ERROR:  missing FROM-clause entry for table "apartment"
   LINE 1: ...SELECT "apartments"."id" FROM "apartments"  WHERE "apartment...
                                                                ^
   : SELECT  "users".* FROM "users" INNER JOIN "residences" ON "residences"."user_id" = "users"."id" WHERE "users"."email" = 'daniela@lehner.biz' AND "residences"."apartment_id" IN (SELECT "apartments"."id" FROM "apartments"  WHERE "apartment"."building_id" = 2895) ORDER BY last_name ASC LIMIT 1
4

1 回答 1

1

在您的修订中,您需要将公寓更改为公寓:

 apartments = Apartment.where('apartments.building_id' => building.id)

以下是使用连接的方法:

#subdomain is already in the conditions so you don't need to do anything
def self.find_for_authentication(conditions={})
  find(:first, :conditions => conditions, 
    :joins => {:residences => {:apartment => :building }})
end

有关使用散列的嵌套连接的更多信息,请参阅以下指南中的第 11.2.4 节。 http://guides.rubyonrails.org/active_record_querying.html#joining-tables

于 2013-05-08T16:02:49.233 回答