我使用友谊联接表在用户之间建立了自引用联接关系,该表看起来像:
用户>友谊>用户(重命名为好友)
在我的索引页面中,我希望有一个按钮,包含两个隐藏的表单,用于创建和销毁每个用户旁边的好友或解除好友关系,具体取决于关系的状态。我的创造关系很好,但对于破坏来说,我有一些问题。现在我正在研究4种可能性,每种可能性都有自己的问题。
jquery
$(document).ready(function() {
$("li.friend-button").on('click', function(event) {
$(this).toggleClass('button-friended friend-button');
$(this).find("form.friend-form:hidden").submit();
});
$("li.button-friended").on('click', function(event) {
$(this).toggleClass('button-friended friend-button');
$(this).find("form.unfriend:hidden").submit();
});
});
ERB
<li class="<%= friended ? "button-friended" : "friend-button" %>">Friend
<!-- From UsersController: @friendship = Friendship.new -->
<%= form_for [user, @friendship], :remote => true, html: { :class => 'friend-form'} do |f| %>
<%= f.submit %> #This creates fine
<% end %>
选项1:
<% friendship = current_user.friendships.find_by_friend_id(user.id)%>
<%= form_for friendship, :method => :delete, :remote => true, html: {class: "unfriend"} do |f| %>
<%= f.submit %> # Works as long as all users are friended, otherwise has error: undefined method `model_name' for NilClass:Class. Since the friendship is nil.
<% end %>
控制器
def destroy
@friendship = Friendship.find(params[:id])
@friendship.destroy
选项2
<%= form_for user, :method => :delete, :url => friendship_path, :remote => true, html: {class: "unfriend"} do |f| %>
<%= f.submit %> # Error: No route matches {:action=>"destroy", :controller=>"friendships"}. Since it's form_for user, but heading to the FrendshipsController (I guess)
<% end %>
是的,我已经看到了:一个长期存在的错误阻止form_for自动使用单个资源。作为一种变通方法,可以直接指定表单的URL,如下所示:form_for@geocoder,url:geocoder_path do|f|
来自边缘导轨
控制器
def destroy
@friendship = current_user.friendships.find_by_friend_id(params[:id])
@friendship.destroy
选项3
<%= form_for [user, @friendship], :url => user_friendship_path, :remote => true, html: {class: "unfriend"} do |f| %>
<%= f.submit %> #Also: No route matches {:action=>"destroy", :controller=>"friendships"}, but no idea why
<% end %>
控制器
def destroy
@friendship = current_user.friendships.find_by_friend_id(params[:user_id])
@friendship.destroy
选项4
<%= form_for [user, @friendship], :method => :delete, :remote => true, html: {class: "unfriend"} do |f| %>
<%= f.submit %>
<% end %> #Page finally renders, but get this from the dev.log:
Started DELETE "/users/4/friendships" for 127.0.0.1 at 2013-07-19 13:56:01 -0400
ActionController::RoutingError (No route matches [DELETE] "/users/4/friendships"):
控制器与O3 相同
相关路线:
user_friendships POST /users/:user_id/friendships(.:format) friendships#create
user_friendship DELETE /users/:user_id/friendships/:id(.:format) friendships#destroy
friendship DELETE /friendships/:id(.:format) friendships#destroy
谢谢,提前。
对于任何有类似问题的人(尽管根据我的研究,你们中的许多人似乎都不是这样)。
所以,我能想出的最好的办法是一个相当糟糕的破解,但它能完成任务。在命令行上,我创建了一个"虚假友谊"
=> #<Friendship id: 51, created_at: "2013-07-20 13:04:28", updated_at: "2013-07-20 13:04:28", user_id: 0, friend_id: 0>
尽管它不一定是假的,但我只是想用id
来解决这个问题:
ActionController::RoutingError(没有路由匹配[DELETE]"/users/8/friends")
这是我从上面的选项4中得到的。
所以,这是代码:
用户控制器:
def index
@users = User.all
@friendship = Friendship.new
@friends = current_user.friends.order('id')
# gives me a "friendship" to enter into friendship delete forms so it routes
# properly, never changes since the delete controller only worries about
# the user_id
@fake_friendship = Friendship.find(51)
end
index.html.erb
<%= form_for [user, @fake_friendship], :method => :delete, :remote => true, html: {class: "unfriend"} do |f| %>
<%= f.submit %>
<% end %>
尝试在@friendship.destroy
之后添加redirect_to friendship_path, status: 303
如果您使用的是GET或POST以外的XHR请求,并在请求后重定向,则某些>浏览器将使用原始请求方法进行重定向。这可能会导致不希望的>行为,例如双重DELETE。要解决此问题,您可以返回303。请参阅其他状态代码>,后面将使用GET请求。
来源:http://api.rubyonrails.org/classes/ActionController/Redirecting.html#method-i-redirect_to