4

Так что я приношу свои извинения за то, как noobish могут возникнуть эти вопросы. Я новичок в рельсах, и в качестве первой задачи я также привел в Neo4J, поскольку он казался лучшим, если я вырасту проект.Создание отношений в модели Neo4J с after_save

Я объясню поток действий, а затем покажу пример кода. Сейчас я пытаюсь добавить шаг 3-5.

  1. Пользователь входит в систему с помощью FB
  2. Первый Войти создает пользовательский узел. Если пользователь существует, он просто извлекает этот пользователь + узел
  3. После создания пользовательского узла камень koala используется для доступа к графическому интерфейсу FB
  4. Получает список друзей каждого друга с помощью приложения.
  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 

Так что в моем 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 

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 

Я не уверен, если я m на правильном пути с тем, как создать узел отношений. Поскольку я только что создал @user, как мне включить это в мой метод check_friends и так правильно получить пользовательский и дружеский узел, чтобы я мог связать их вместе.

Сейчас он не знает, что пользователь и friend_user являются узлами

Если вы видите другой плохой код практики, пожалуйста, дайте мне знать!

Заблаговременно: Спасибо за помощь @subvertallchris. Я уверен, что вы ответите на многие мои вопросы, подобные этому.

+0

Hahaha! Вы смотрите в будущее! Это большой вопрос. Дайте мне несколько минут, чтобы набрать его. – subvertallchris

+0

Также, не стесняйтесь, напишите мне, если вам когда-нибудь понадобится помощь, и не хотите размещать здесь по какой-либо причине. Я изучил Ruby, Rails и Neo4j в то же время, потому что это соответствовало моему проекту! – subvertallchris

ответ

5

Это действительно отличный вопрос! Я думаю, что вы на правильном пути, но есть несколько вещей, которые вы можете изменить.

Во-первых, вам необходимо настроить этот метод has_many. Ваши ассоциации всегда должны заканчиваться в узле, не ActiveRel классов, так что вам нужно переписать, что, как-то вроде этого:

has_many :both, :friends, model_class: 'User', rel_class: 'Friendship'

Вы столкнетесь с некоторыми проблемами в противном случае.

Возможно, вы захотите рассмотреть вопрос о переименовании вашего типа отношений в интересах стилистической последовательности Neo4j. У меня много плохих примеров, поэтому извините, если я дал вам плохие идеи. FRIENDS_WITH - лучшее название отношений.

Что касается решения вашей большой проблемы, здесь вы можете многое сделать.

EDIT! Дерьмо, я забыл самую важную часть! Ditch, что after_save callback и сделать нагрузку существующих/создать новое поведение пользователя два метода.

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 

Это поможет решить вашу проблему с ее запуском. Вы можете обернуть все это в транзакцию, поэтому прочитайте об этом в вики.

Но мы не закончили. Давайте посмотрим на исходный 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 

Вы на самом деле не передавая ему аргумент, поэтому избавиться от этого. Кроме того, если вы знаете, что ищете только один узел, используйте 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 

Метод create_friendship должен должен возвращать истинным или ложным, так просто сделать, что последнее утверждение метода делает это, и вы можете вернуть то, что он вернется. Это так же просто, как это:

def self.create_friendship(user, friend_node) 
    Friendship.new(from_node: user, to_node: friend_node).save 
end 

create не возвращается истинным или ложным, он возвращает результирующий объект, поэтому цепочки 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 

Это очень легко для ваших моделей стать этими грязными сумками для захвата. Многие блоги будут поощрять это. Борьба с желанием!

Это должно быть хорошим началом. Дайте мне знать, если у вас есть какие-либо вопросы или я что-то прикрутил, есть много кода, и, возможно, мне может понадобиться прояснить или изменить некоторые из них. Надеюсь, что это поможет.

+0

Хорошо, ничего не выдает ошибку, но она все еще не сохраняет отношения. Я думаю, что friend_node может быть пустым. Я хочу посмотреть, правильно ли он находит узел 'friend_node = User.find_by (uid: friend [" id "])' Какие хорошие способы проверить, что что-то пусто в rails/ruby ​​в моей модели и напечатать его в моем представлении ? – Clam

+0

Я попрошу вас немного о дружбе, возможно, в слабом – Clam

 Смежные вопросы

  • Нет связанных вопросов^_^