has_many通过相同的表Rails

时间:2017-05-20 00:45:37

标签: ruby-on-rails has-many-through

我想创建一个允许“用户”关注其他用户的Rails应用。我对更复杂的关系是半新的,并且我试图第一次设置has_many。我希望朋友能够关注其他用户。

这是我的联接表:

class Following < ApplicationRecord

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

end

这是我的用户表:

class User < ApplicationRecord

has_many :followings
has_many :followers, through: :followings

end

这是我的架构:

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

我不知道如何设置表单来实际创建关系。在用户视图中,我有这个,但它不起作用。

<%= 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 %>

正如我所说,我对这种关系很陌生。我需要帮助。我不知道如何通过表单链接记录。

我正在关注本教程:https://teamtreehouse.com/library/what-is-a-hasmany-through-association-in-ruby-on-rails

1 个答案:

答案 0 :(得分:0)

我假设你有一个current_user方法返回登录用户 - 就像Devise提供的那样。如果不是,您需要先设置身份验证。

创建嵌套路线:

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

向Follow添加验证以避免重复:

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

向用户添加实用程序方法,以查看他是否关注其他用户:

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

然后我们可以在/users/show.html.erb视图中添加Follow和Unfollow按钮(它们实际上是表单)。

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

请注意,我们不需要任何表单参数,因为我们使用嵌套路由(POST /users/:user_id/followings)来传递用户ID(跟随谁),我们从会话中获取当前用户。

然后我们可以设置我们的控制器:

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