Cla*_*lam 4 ruby-on-rails neo4j facebook-graph-api koala-gem neo4j.rb
所以我为这些问题看起来多么荒谬而道歉.我是rails的新手,作为第一个任务,我也带来了Neo4J,因为如果我发展这个项目,它似乎是最合适的.
我将解释操作流程然后显示一些示例代码.我现在尝试在步骤3-5中添加.
因为3-5只需要在用户第一次加入时发生,我想我可以在与after_save回调相关的方法中执行此操作.这个逻辑有一个缺陷,因为我需要在某个时候用其他属性更新用户,它会再次调用after_save.我可以通过更新来防止这种情况发生吗?
SessionsController供参考
def create
user = User.from_omniauth(env["omniauth.auth"])
session[:user_id] = user.id
redirect_to root_url
end
def destroy
session.delete(:user_id)
redirect_to root_path
end
Run Code Online (Sandbox Code Playgroud)
所以在我的user.rb中我有这样的东西
has_many :both, :friendships
after_save :check_friends
def self.from_omniauth(auth)
@user = User.where(auth.slice(:provider, :uid)).first
unless @user
@user = User.new
# assign a bunch of attributes to @user
@user.save!
end
return @user
end
def facebook
@facebook ||= Koala::Facebook::API.new(oauth_token)
block_given? ? yield(@facebook) : @facebook
rescue Koala::Facebook::APIError => e
logger.info e.to_s
nil
end
def friends_count
facebook { |fb| fb.get_connection("me", "friends", summary: {}) }
end
def check_friends(friendships)
facebook.get_connection("me", "friends").each do |friend|
friend_id = friend["id"]
friend_node = User.where(friend_id)
Friendship.create_friendship(user,friend_node)
return true
end
end
Run Code Online (Sandbox Code Playgroud)
friendship.rb
from_class User
to_class User
type 'friendship'
def self.create_friendship(user,friend_node)
friendship = Friendship.create(from_node: user, to_node: friend_node)
end
Run Code Online (Sandbox Code Playgroud)
我不确定我是否在如何创建关系节点的正确轨道上.正如我刚刚创建的那样@user,如何将其合并到我的check_friends方法中并正确检索用户和朋友节点,以便将两者链接在一起.
现在它不知道user和friend_user是节点
如果你看到其他不良代码的做法,请告诉我!
提前:感谢@subvertallchris的帮助.我相信你会回答我的很多问题.
这是一个非常好的问题!我认为你走的正确,但有一些事情你可以改变.
首先,您需要调整该has_many方法.您的关联总是需要终止于节点,而不是ActiveRel类,因此您需要将其重写为如下所示:
has_many :both, :friends, model_class: 'User', rel_class: 'Friendship'
否则你会遇到一些问题.
您可能需要考虑重新命名您的关系类型,以符合Neo4j的风格一致性.我有很多不好的例子,如果我给你不好的想法,那就很抱歉.FRIENDS_WITH将是一个更好的关系名称.
至于处理你的大问题,你可以在这里做很多事情.
编辑!废话,我忘记了最重要的部分!沟通那个after_save回调并使加载存在/创建新用户行为的两种方法.
class SessionsController < ApplicationController
def create
user = User.from_omniauth(env["omniauth.auth"])
@user = user.nil? ? User.create_from_omniauth(env["omniauth.auth"]) : user
session[:user_id] = @user.id
redirect_to root_url
end
def destroy
session.delete(:user_id)
redirect_to root_path
end
end
class User
include Neo4j::ActiveNode
# lots of other properties
has_many :both, :friends, model_class: 'User', rel_class: 'Friendship'
def self.from_omniauth(auth)
User.where(auth.slice(:provider, :uid)).limit(1).first
end
def self.create_from_omniauth(auth)
user = User.new
# assign a bunch of attributes to user
if user.save!
user.check_friends
else
# raise an error -- your user was neither found nor created
end
user
end
# more stuff
end
Run Code Online (Sandbox Code Playgroud)
这将解决你的问题,让它开始.您可能希望将整个事物包装在事务中,因此请在Wiki中阅读.
但我们还没有完成.让我们看看你的原作check_friends:
def check_friends(friendships)
facebook.get_connection("me", "friends").each do |friend|
friend_id = friend["id"]
friend_node = User.where(friend_id)
Friendship.create_friendship(user,friend_node)
return true
end
end
Run Code Online (Sandbox Code Playgroud)
你实际上并没有把它作为一个论据,所以摆脱它.此外,如果您知道自己只是在寻找单个节点,请使用find_by.我将假设facebook_id每个用户都有一个属性.
def check_friends
facebook.get_connection("me", "friends").each do |friend|
friend_node = User.find_by(facebook_id: friend["id"])
Friendship.create_friendship(user,friend_node) unless friend_node.blank?
end
end
Run Code Online (Sandbox Code Playgroud)
该create_friendship方法应该返回true或false,所以只要使方法的最后一个语句执行该操作,您就可以返回它返回的任何内容.这很容易:
def self.create_friendship(user, friend_node)
Friendship.new(from_node: user, to_node: friend_node).save
end
Run Code Online (Sandbox Code Playgroud)
create不返回true或false,它返回结果对象,因此链接save到您的新对象将获得您想要的.除非您计划在方法中更多地使用它,否则您不需要在那里设置变量.
此时,您可以轻松地after_create向ActiveRel模型添加一个回调,该回调将执行某些操作from_node,这始终是您刚刚创建的用户.您可以从那里更新用户的属性.控制这种行为正是ActiveRel存在的原因.
我可能还会再修改一下.首先将您的facebook东西移动到模块中.它将使您的用户模型更清洁,更专注.
# models/concerns/facebook.rb
module Facebook
extend ActiveSupport::Concern
def facebook
@facebook ||= Koala::Facebook::API.new(oauth_token)
block_given? ? yield(@facebook) : @facebook
rescue Koala::Facebook::APIError => e
logger.info e.to_s
nil
end
def friends_count
facebook { |fb| fb.get_connection("me", "friends", summary: {}) }
end
end
# now back in User...
class User
include Neo4j::ActiveNode
include Facebook
# more code...
end
Run Code Online (Sandbox Code Playgroud)
你的模特很容易成为这些凌乱的抓包.很多博客会鼓励这一点.战斗的冲动!
这应该是一个好的开始.如果您有任何问题或者我搞砸了什么问题,请告诉我,有很多代码,我可能需要澄清或调整一些代码.但希望它有所帮助.
| 归档时间: |
|
| 查看次数: |
666 次 |
| 最近记录: |