2017-05-20 1 views
0

Je veux créer une application Rails qui permette aux utilisateurs de suivre d'autres utilisateurs. Je suis semi-nouveau à des relations plus complexes et je tente de mettre en place has_many à travers pour la première fois. Je veux que mes amis puissent suivre d'autres utilisateurs.has_many à travers la même table Rails

Voici ma table de jointure:

class Following < ApplicationRecord 

belongs_to :user 
belongs_to :follower, class_name: "User" 

end 

Voici ma table d'utilisateurs:

class User < ApplicationRecord 

has_many :followings 
has_many :followers, through: :followings 

end 

Voici mon schéma:

create_table "followings", force: :cascade do |t| 
t.integer "user_id" 
t.integer "follower_id" 
t.datetime "created_at", null: false 
t.datetime "updated_at", null: false 
end 

create_table "users", force: :cascade do |t| 
t.string "name" 
t.datetime "created_at", null: false 
t.datetime "updated_at", null: false 
end 

Je ne sais pas comment définir un formulaire pour créer réellement la relation. Dans une vue des utilisateurs, j'ai ceci, mais cela ne fonctionne pas.

<%= form_for @following do |f| %> 
<%= f.hidden_field :follower_id, :value => @user %> 
<%= f.select :user_id, @users.collect { |u| [u.name, u.id] } %> 
<%= f.submit %> 
<% end %> 

Comme je l'ai dit, je suis très nouveau dans ce type de relation. J'ai besoin d'aide. Je ne sais pas comment lier les enregistrements à travers un formulaire.

Je suivais ce tutoriel: https://teamtreehouse.com/library/what-is-a-hasmany-through-association-in-ruby-on-rails

Répondre

0

Je suppose que vous avez une méthode current_user qui renvoie l'utilisateur connecté - comme ce qui fournit définissent. Sinon, vous devez d'abord configurer l'authentification.

Créer un itinéraire imbriqué:

# config/routes.rb 
resources :users, only: [] do 
    resources :followings, only: [:create, :destroy], shallow: true 
end 

Ajouter une validation à la suite pour éviter les doublons:

class Following < ApplicationRecord 
    belongs_to :user 
    belongs_to :follower, class_name: "User" 
    validates_uniqueness_of :user_id, scope: 'follower_id' 
end 

Ajouter une méthode utilitaire pour l'utilisateur pour voir s'il suit un autre utilisateur:

class User < ApplicationRecord 
    has_many :followings 
    has_many :followers, through: :followings 

    def following?(user) 
    followings.exist?(user: user) 
    end 

    def find_following(user) 
    followings.find_by(user: user) 
    end 
end 

Nous pouvons ensuite ajouter les boutons Suivre et Ne plus suivre (ils sont en fait des formulaires) au /users/show.html.erb Voir.

<% if current_user.following?(@user) %> 
    <%= button_to "Unfollow", current_user.find_following(@user), method: :delete %> 
<% else %> 
    <%= button_to "Follow", [@user, @user.followings.new] %> 
<% end %> 

Notez que nous ne avons pas besoin de forme params puisque nous utilisons un itinéraire imbriquée (POST /users/:user_id/followings) pour passer l'ID utilisateur (qui obtient suivi) et nous obtenons l'utilisateur en cours de la session.

Nous pouvons alors configurer notre contrôleur:

class FollowingsController < ApplicationController 
    # POST /users/:user_id/followings 
    def create 
    @user = User.find(params[:user_id]) 
    @following = Following.new(user: @user, follower: current_user) 
    if @following.save 
     redirect_to @user, success: "You are now following #{ @user.name }" 
    else 
     redirect_to @user, error: "Could not create following" 
    end 
    end 

    # DELETE /followings/:id 
    def destroy 
    @following = Following.find(params[:id]) 
    @following.destroy 
    redirect_to @following.user, success: "You are no longer following #{ @user.name }" 
    end 
end