如何在rails中调用一对一的关系

时间:2014-12-07 15:05:45

标签: ruby-on-rails postgresql

我是rails的新手,我想知道如何获取一对一的关系。我想要获取用户城市。在我的postgresql数据库中,我有:

cities Table: 

city:varchar
zipcode: integer

users Table

name:varchar 
city_id:int

在城市和用户模型中我有:

class City < ActiveRecord::Base
  belongs_to :user
end

class User < ActiveRecord::Base
  has_one :city

    devise :database_authenticatable, :registerable,
           :recoverable, :rememberable, :trackable, :validatable

end

我在搜索控制器中尝试了以下操作,但在登录时无效:

current_user.city

我收到以下错误

Processing by SearchController#index as HTML
  Parameters: {"utf8"=>"✓", "q"=>"", "criteria"=>"1", "commit"=>"Search"}
  User Load (1.1ms)  SELECT  "users".* FROM "users"  WHERE "users"."id" = 6  ORDER BY "users"."id" ASC LIMIT 1
PG::UndefinedColumn: ERROR:  column cities.user_id does not exist
LINE 1: SELECT  "cities".* FROM "cities"  WHERE "cities"."user_id" =...
                                                ^
: SELECT  "cities".* FROM "cities"  WHERE "cities"."user_id" = $1 LIMIT 1
Completed 500 Internal Server Error in 11ms

ActiveRecord::StatementInvalid (PG::UndefinedColumn: ERROR:  column cities.user_id does not exist
LINE 1: SELECT  "cities".* FROM "cities"  WHERE "cities"."user_id" =...
                                                ^
: SELECT  "cities".* FROM "cities"  WHERE "cities"."user_id" = $1 LIMIT 1):

为什么我想在users表中添加一个user_id列,当我在users表中有城市外键时?我不想将user_id添加到cities表中。

2 个答案:

答案 0 :(得分:1)

查看has_one和belogns_to的文档,

belongs_to(name, options = {})
Specifies a one-to-one association with another class. This method should only be used if this class    
contains the foreign key. If the other class contains the foreign key, then you should use has_one  
instead.

由于用户表具有外键,您应该像这样更改模型定义

class City < ActiveRecord::Base
  has_one :user
end

class User < ActiveRecord::Base
  belongs_to :city
end

答案 1 :(得分:1)

您可以将has_one :through association与联接表一起使用。下面给你一些例子。

用户模型:

class User < ActiveRecord::Base
  has_one :city, through: :user_city
  has_one :user_city
end

城市模型:

class City < ActiveRecord::Base
  belongs_to :user
end

用户城市加入模式:

class UserCity < ActiveRecord::Base
  belongs_to :city
  belongs_to :user
end

连接表的迁移:

class JoinUserCity < ActiveRecord::Migration
  def change
    create_table :user_cities do |t|
      t.integer :user_id
      t.integer :city_id
    end
  end
end

在rails控制台中测试:

=> u = User.create
  (0.1ms)  begin transaction
 SQL (0.5ms)  INSERT INTO "users" ("created_at", "updated_at") VALUES (?, ?)  [["created_at", "2014-12-07 15:47:14.595728"], ["updated_at", "2014-12-07 15:47:14.595728"]]
  (3.3ms)  commit transaction
=> #<User id: 4, created_at: "2014-12-07 15:47:14", updated_at: "2014-12-07 15:47:14">
=> u.city
  City Load (0.2ms)  SELECT  "cities".* FROM "cities" INNER JOIN "user_cities" ON "cities"."id" = "user_cities"."city_id" WHERE "user_cities"."user_id" = ? LIMIT 1  [["user_id", 4]]
=> nil
=> c = City.create
  (0.1ms)  begin transaction
  SQL (0.5ms)  INSERT INTO "cities" ("created_at", "updated_at") VALUES (?, ?)  [["created_at", "2014-12-07 15:47:24.535039"], ["updated_at", "2014-12-07 15:47:24.535039"]]
  (3.3ms)  commit transaction
=> #<City id: 1, created_at: "2014-12-07 15:47:24", updated_at: "2014-12-07 15:47:24">
irb(main):004:0> u.city = c
  UserCity Load (0.3ms)  SELECT  "user_cities".* FROM "user_cities"  WHERE "user_cities"."user_id" = ? LIMIT 1  [["user_id", 4]]
   (0.1ms)  begin transaction
  SQL (0.4ms)  INSERT INTO "user_cities" ("city_id", "user_id") VALUES (?, ?)  [["city_id", 1], ["user_id", 4]]
   (1.0ms)  commit transaction
=> #<City id: 1, created_at: "2014-12-07 15:47:24", updated_at: "2014-12-07 15:47:24">
irb(main):005:0> u.save
   (0.1ms)  begin transaction
   (0.1ms)  commit transaction
=> true
=> u = User.last
  User Load (0.3ms)  SELECT  "users".* FROM "users"   ORDER BY "users"."id" DESC LIMIT 1
=> #<User id: 4, created_at: "2014-12-07 15:47:14", updated_at: "2014-12-07 15:47:14">
=> u.city
  City Load (0.2ms)  SELECT  "cities".* FROM "cities" INNER JOIN "user_cities" ON "cities"."id" = "user_cities"."city_id" WHERE "user_cities"."user_id" = ? LIMIT 1  [["user_id", 4]]
=> #<City id: 1, created_at: "2014-12-07 15:47:24", updated_at: "2014-12-07 15:47:24">