我一直在努力让我的rails项目只用用户唯一的facebook数据更新用户表。但是,我无法获取Facebook数据。我尝试了多种方法,但最终代码似乎是hacky并使用强力更新列(以及创建重复记录)
以下是我的例子:
用户
class User < ActiveRecord::Base
has_one :facebook
def self.create_with_omniauth(auth)
create! do |user|
user.email = auth['email']
end
end
end
实
class Facebook < ActiveRecord::Base
belongs_to :user
def self.create_with_omniauth(auth)
create! do |fb|
if auth['info']
fb.profile_link = auth['info']['profile_link'] || "test"
end
end
end
迁移:
class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.string :email
t.timestamps null: false
end
end
end
class Facebooks < ActiveRecord::Migration
create_table :facebooks do |f|
f.belongs_to :user, index: true, :unique => true
f.string :profile_link
f.timestamps null: false
end
end
创建用户时: SessionController(为用户调用create时)
def create
auth = request.env["omniauth.auth"]
user = User.where(:provider => auth['provider'],
:uid => auth['uid'].to_s).first || User.create_with_omniauth(auth)
Facebook.create_with_omniauth(auth)
到目前为止,我对Rails ActiveRecord的理解是,如果我使用“has_one”和“belongs_to”,那么如果创建了用户表,它应该自动在facebook表中创建记录吗?
我的预期数据是:
SELECT * FROM users where id = 1;
id email
1 email@email.com
SELECT * FROM facebooks where user_id = 1;
id user_id profile_link
1 1 facebook.com/profile_link
facebook根本没有创建记录。
不确定我哪里出错了,我已经按照大量的教程进行操作,希望能掌握有效的记录。
谢谢!
@val的附带问题 def self.facebook_handler(user,auth)
if Facebook.exists?(user_id: id)
user = Facebook.find_by(user_id: id)
user.update(name: me['name'])
user.update(first_name: me['first_name'])
else
create! do |fb|
if me
fb.name = me['name']
fb.user_id = user.id
fb.first_name = me['first_name']
end
end
end
end
---否则每次登录时都会不断插入新记录。
答案 0 :(得分:1)
在activerecord和Rails中有这么多移动的部分。我认为您必须回到迁移并解决一些问题,为MVC的视图和控制器部分设置坚实的模型基础。
我在您发布的迁移中看到了模型类型的功能,但这并不能很好地为您服务。迁移应尽可能灵活,约束应放在model.rb上。
您的用户模型看起来很好。
class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.string :email
t.timestamps null: false
end
end
end
你的facebook迁移应该看起来更像这样。创建一个t.reference并添加索引。
class Facebooks < ActiveRecord::Migration
create_table :facebooks do |f|
t.references :user, index: true
f.string :profile_link
f.timestamps null: false
end
add_index :facebooks, [:user_id]
end
然后在您的Facebook模型中,您可以应用限制和要求
facebook.rb
belongs_to :user,
validates :user_id, presence: true, :unique => true
您的用户model.rb应包含:
has_one :facebook
关于您在控制器中的更高级别操作还有其他一些问题,但我认为设置模型可以帮助您朝着目标前进。
答案 1 :(得分:1)
下面的模型约束以及索引设置看起来会导致ActiveRecord到ROLLBACK并且不会为给定用户添加重复的facebook记录。但听起来重复的是添加到facebook表。那怎么样?
facebook.rb
belongs_to :user,
validates :user_id, presence: true, :unique => true
...
user.rb
has_one :facebook
&#39; if&#39;你写的这个条目对我来说就好像没有必要设置用户/ facebook之间的关系并在模型和数据库表中工作,这让我觉得某处缺少验证。
要尝试一些事情,在Facebook数据描述上进行模型迁移(更改),以便为db表本身的user_id字段添加:唯一验证器。 (没有change_index命令,你必须删除然后添加。)
remove_index :facebooks, [:user_d]
add_index :facebooks, [:user_id], :unique => true
尝试拍摄&#39; if&#39;逻辑出来,看看你是否得到了欺骗。在继续执行控制器中的逻辑之前,需要正确设置关系,否则您将试图解开它。
对于您在评论中提出的问题,范围很适合根据参数创建集合。所以,在你的user.rb模型中:
scope :important_thing_is_true, -> { where(:provider => auth['provider'],:uid => auth['uid'].to_s).first) }
user.important_thing_is_true引用的是返回集合或nil,然后您可以在其他逻辑或显示中测试或使用等等。但是,如果您没有重复记录问题,可能此范围不是& #39; t需要。