我已按照本指南:http://www.tobyh.com/thoughts/4为社交应用制作双向友谊系统。经过一个多星期的工作后,按照该指南到目前为止我已经完成了这项工作,但最终产品存在很多严重的问题。只有前三分之一有效 - 发送好友请求。接受或拒绝朋友请求都不起作用。
要开始解释这一点,以下是相关部分:
的routes.rb
resources :friendships, only: [:create, :update, :destroy]
friendship.rb
class Friendship < ActiveRecord::Base
belongs_to :user
belongs_to :friend, :class_name => 'User'
end
user.rb
class User < ActiveRecord::Base
has_many :friendships, dependent: :destroy
has_many :received_friendships, class_name: "Friendship", foreign_key: "friend_id", dependent: :destroy
has_many :active_friends, -> { where(friendships: { accepted: true}) }, through: :friendships, source: :friend
has_many :received_friends, -> { where(friendships: { accepted: true}) }, through: :received_friendships, source: :user
has_many :pending_friends, -> { where(friendships: { accepted: false}) }, through: :friendships, source: :friend
has_many :requested_friendships, -> { where(friendships: { accepted: false}) }, through: :received_friendships, source: :user
attr_accessor :remember_token, :activation_token, :reset_token (I've spent more than 20 hours on slogging through google and
stackoverflow alone, and I have a fuzzy memory of someone saying that attr_accessor might be relevant to this problem, but
I only saw it mentioned in a single question out of more than 20, so I'm not sure if it really is relevant.)
friendships_controller.rb
class FriendshipsController < ApplicationController
def create
@friendship = current_user.friendships.build(friend_id: params[:friend_id])
if @friendship.save
flash[:notice] = "Friend request sent!"
redirect_to :back
else
flash[:error] = "Unable to send friend request."
redirect_to :back
end
end
def update
@friendship = Friendship.find_by(id: params[:id])
@friendship.update(:accepted, true)
if @friendship.save
redirect_to root_url, notice: "Friend request accepted."
else
redirect_to root_url, notice: "Unable to accept friend request."
end
end
def destroy
@friendship = Friendship.find_by(id: params[:id])
@friendship.destroy
flash[:notice] = "Friend request declined."
redirect_to :back
end
end
_user.html.erb,它是显示每个用户的索引页面,具有分页功能。这是其中唯一相关的部分:
<% if logged_in? && !current_user?(user) %>
<%= link_to "Add Friend", friendships_path(:friend_id => user), :method => :post %>
<% end %>
和show.html.erb,显示用户的个人资料页面。在此页面和用户索引页面上,您可以查看和使用&#34;添加好友&#34;按钮,只要您以该用户以外的其他人身份登录即可。此外,由于索引,如果您尝试向某人发送2个朋友请求,则第二个朋友请求将失败。
<% if logged_in? && !current_user?(@user) %>
<%= link_to "Add Friend", friendships_path(:friend_id => @user), :method => :post %>
<% end %>
...
<ul class="nav nav-tabs">
...
<% if logged_in? && current_user?(@user) %>
<li><a data-toggle="tab" href="#friendreqs">Friend Requests</a></li>
<% end %>
</ul>
...
<div id="friendreqs" class="tab-pane fade">
<h3>Friend Requests</h3>
<ul>
<% if current_user?(@user) %>
<% current_user.requested_friendships.each do |request| %>
<li>
<%= request.name %>
<%= link_to "Accept", friendship_path(id: request.id), method: "put" %>
<%= link_to "Decline", friendship_path(id: request.id), method: :delete %>
</li>
<% end %>
<% end %>
</ul>
</div>
现在,无论您是在用户的个人资料页面上使用“添加好友”链接还是在用户索引中使用其名称旁边的“添加好友”链接,发送好友请求似乎都有效。登录用户#3后,在控制台的图片中,将用户#2作为朋友从他们的个人资料页面添加,并通过索引页面将用户#1添加为朋友:http://i.imgur.com/MbsBKot.png此处&#39 ;一张SQL数据库浏览器的图片似乎也确认已成功发送了初始好友请求:http://i.imgur.com/cX45vm8.png&#34;已接受&#34;在发送好友请求后默认设置为false,因为我希望它是&#34; facebook风格&#34;朋友请求系统,而不是单向&#34;推特风格&#34;之一。
由于花费了大量时间处理此问题,我遇到了各种各样的问题和错误消息,其中大部分都不再重要。从收到朋友请求开始,点击&#34;拒绝&#34;在您的个人资料页面上。
起初,一切似乎都很好。您的个人资料页面会刷新,并且&#34;朋友请求被拒绝。&#34; friendships_controller.rb中的消息按预期显示。但是,当您点击“朋友请求”标签时,您会看到您拒绝的朋友请求仍然存在。这里有一张图片,没有上面和左边的flash消息:http://i.imgur.com/Dg1uTXf.png如果你第二次(或更多)尝试拒绝好友请求,你会收到标题中的错误消息问题。这也是一张照片:http://i.imgur.com/XBhNtkF.png
这似乎表明它失败了,因为好友请求已经成功被拒绝了,对吧?据我所知:不!我认为这不是真的,因为这张图片的内容:http://i.imgur.com/UOIYnHP.png下载了数据库的新副本后,它声称有一个甚至更大的数字友谊比以前好! 3个朋友请求而不是2个,其中一个没有附加friend_id。这也可以解释为什么朋友请求在“朋友请求”选项卡下仍然存在。
最重要的是,如果您注销,请登录好友请求发件人的帐户,并尝试向接收方发送第二个好友请求,您将收到以下错误消息:http://i.imgur.com/q0WsVCB.png FriendsitesController中的SQLite3 :: ConstraintException #create UNIQUE约束失败:friendships.user_id,friendships.friend_id 我非常确定这是为友情添加索引的结果,这会阻止用户从同一个人那里收到2个或更多朋友请求。这再次意味着单击拒绝并不能真正删除朋友请求,只有&#34; friend_id&#34;它的一部分,它具有在数据库中创建第三个友谊条目的意外效果。
呼!这是相当多的信息,但这只涵盖了&#34;衰落&#34;链接。现在为&#34;接受&#34;链接!
如果您登录,看到新朋友请求,并尝试接受它,您将收到与尝试连续2次拒绝朋友请求时相同的错误消息,但使用此消息引用update方法而不是destroy方法:http://i.imgur.com/IHptXDu.png FriendshipsController#update中的NoMethodError 未定义的方法`update&#39;为零:NilClass 我不知道为什么会这样。
当我写这个问题并拍照时,我注意到了这个重复的行:&#34; friendship_path(id:request.id)&#34;在show.html.erb下,并考虑与此数据库图片进行比较:http://i.imgur.com/UOIYnHP.png如果,当点击拒绝删除友情请求时,它只删除请求该朋友的用户的ID请求(在该图片中,是user_id,而不是friend_id)?问题可能是show.html.erb下的Decline和Accept链接的格式,其他一切都很好..?
我想我写的只是我能写的所有东西!对不起这个问题有多久了,谢谢你花时间阅读它;我衷心感激它!
答案 0 :(得分:1)
我打算在一周前添加这个,但是这里最终为我工作了。
friendship.rb:
class Friendship < ActiveRecord::Base
belongs_to :user
belongs_to :friend, :class_name => 'User'
validates :user_id, presence: true
validates :friend_id, presence: true
end
user.rb:
class User < ActiveRecord::Base
has_many :friendships, dependent: :destroy
has_many :received_friendships, class_name: "Friendship", foreign_key: "friend_id", dependent: :destroy
has_many :passive_friends, -> { where(friendships: { accepted: true}) }, through: :received_friendships, source: :user
has_many :active_friends, -> { where(friendships: { accepted: true}) }, :through => :friendships, :source => :friend
has_many :requested_friendships, -> { where(friendships: { accepted: false}) }, through: :received_friendships, source: :user
has_many :pending_friends, -> { where(friendships: { accepted: false}) }, :through => :friendships, :source => :friend
friendships_controller.rb:
class FriendshipsController < ApplicationController
def create
@friendship = current_user.friendships.build(friend_id: params[:friend_id])
if @friendship.save
flash[:notice] = "Friend request sent!"
redirect_to :back
else
errors.add(:friendships, "Unable to send friend request.")
redirect_to :back
end
end
def update
@friendship = Friendship.where(friend_id: [current_user, params[:id]], user_id: [current_user, params[:id]]).first
@friendship.update(accepted: true)
if @friendship.save
redirect_to :back, notice: "Friend request accepted."
else
redirect_to :back, notice: "Unable to accept friend request."
end
end
def destroy
@friendship = Friendship.where(friend_id: [current_user, params[:id]]).where(user_id: [current_user, params[:id]]).last
@friendship.destroy
flash[:notice] = "Friend request declined."
redirect_to :back
end
end
show.html.erb:
<% current_user.requested_friendships.each do |request| %>
<% if request.id == @user.id %>
<%= link_to "Accept Friend Request", friendship_path(id: request.id), method: "put" %><br>
<%= link_to "Decline Friend Request", friendship_path(id: request.id), method: :delete %>
<% end %>
<% end %>
<% if logged_in? && !current_user?(@user) && Friendship.where(friend_id: [current_user, params[:id]], user_id: [current_user, params[:id]]).first == nil %>
<%= link_to "Add Friend", friendships_path(:friend_id => @user), :method => :post %>
<% end %>
其他一切都是一样的。