Mongoid::Errors::AmbiguousRelationship 在用户#show
Mongoid::Errors::AmbiguousRelationship in Users#show
我使用 ruby '2.5.0', rails, '5.2.2', mongoid '7.0.2' 并设计
我尝试添加跟随功能,但我在 mongoid '7.0.2' 中出现此错误
message: Ambiguous relations
@options={:class_name=>"User"}, @extension=nil, @module_path="",
@polymorphic=false, @default_foreign_key_field="follower_id",
@foreign_key="follower_id", @indexed=false, @class_name="User",
@klass=User, @validate=false>,
@options={:class_name=>"User"}, @extension=nil, @module_path="",
@polymorphic=false, @default_foreign_key_field="followed_id",
@foreign_key="followed_id", @indexed=false, @class_name="User",
@klass=User, @validate=false> defined on Relationship. summary: When
Mongoid attempts to set an inverse document of a relation in memory,
it needs to know which relation it belongs to. When setting
:relationships, Mongoid looked on the class User for a matching
relation, but multiples were found that could potentially match:
@options={:class_name=>"User"}, @extension=nil, @module_path="",
@polymorphic=false, @default_foreign_key_field="follower_id",
@foreign_key="follower_id", @indexed=false, @class_name="User",
@klass=User, @validate=false>,
@options={:class_name=>"User"}, @extension=nil, @module_path="",
@polymorphic=false, @default_foreign_key_field="followed_id",
@foreign_key="followed_id", @indexed=false, @class_name="User",
@klass=User, @validate=false>. resolution: On the :relationships
relation on User you must add an :inverse_of option to specify the
exact relationship on Relationship that is the opposite of
:relationships.
user.rb
class User
include Mongoid::Document
field :email, type: String, default: ""
has_many :relationships, foreign_key: "follower_id", dependent: :destroy
has_many :reverse_relationships, foreign_key: "followed_id", class_name: "Relationship", dependent: :destroy
def retrieve_users_for_ids(user_ids)
users = []
User.in(id: user_ids).each do |user|
users << user
end
users
end
def followed_users
user_ids = []
relationships.each do |relationship|
user_ids << relationship.followed_id
end
return retrieve_users_for_ids(user_ids)
end
def followers
user_ids = []
reverse_relationships.each do |relationship|
user_ids << relationship.follower_id
end
return retrieve_users_for_ids(user_ids)
end
def following?(other_user)
relationships.where(followed_id: other_user.id).first
end
def follow!(other_user)
relationships.create!(followed_id: other_user.id)
end
def unfollow!(other_user)
relationships.where(followed_id: other_user.id).first.destroy
end
end
_follow.html.erb
<%= form_for(current_user.relationships.build(followed_id: @user.id),
remote: true) do |f| %>
<%= f.hidden_field :followed_id %>
<%= f.submit 'Follow', data: {disable_with: 'Follow...'}, class: 'btn btn-d' %>
<% end %>
找到可行的解决方案
user.rb
class User
include Mongoid::Document
has_and_belongs_to_many :following, class_name: 'User', inverse_of: :followers
has_and_belongs_to_many :followers, class_name: 'User', inverse_of: :following
def follow(other_user)
self.following << other_user
other_user.followers << self
end
def unfollow(other_user)
self.following.delete(other_user)
other_user.followers.delete(self)
end
def following?(other_user)
self.following.include?(other_user)
end
end
users_controller.rb
class UsersController < ApplicationController
def following
@title = 'Following'
@user = User.find(params[:id])
@users = @user.following.page(params[:page])
render 'show_follow'
end
def followers
@title = 'Followers'
@user = User.find(params[:id])
@users = @user.followers.page(params[:page])
render 'show_follow'
end
end
relationships_controller.rb
class RelationshipsController < ApplicationController
def create
@user = User.find(params[:user_id])
current_user.follow(@user)
respond_to do |format|
format.html { redirect_to @user }
format.js
end
end
def destroy
@user = User.find(params[:user_id])
current_user.unfollow(@user)
respond_to do |format|
format.html { redirect_to @user }
format.js
end
end
end
routes.rb
Rails.application.routes.draw do
resources :users do
member do
get :following, :followers
end
end
post '/follow/', to: 'relationships#create'
delete '/unfollow', to: 'relationships#destroy'
end
views/relationships/create.js.erb
$("#follow_form").html("<%= escape_javascript(render('users/unfollow')) %>")
$("#followers").html('<%= @user.followers.count %>')
views/relationships/destroy.js.erb
$("#follow_form").html("<%= escape_javascript(render('users/follow')) %>")
$("#followers").html('<%= @user.followers.count %>')
views/users/_follow_form.html.erb
<% unless current_user?(@user) %>
<div id="follow_form">
<% if current_user.following?(@user) %>
<%= render 'unfollow' %>
<% else %>
<%= render 'follow' %>
<% end %>
</div>
<% end %>
views/users/_follow.html.erb
<%= form_tag "/follow", method: :post , remote: true do %>
<%= hidden_field_tag :user_id, @user.id %>
<%= submit_tag "Follow", data: {disable_with: 'Follow...'}, class: "btn btn-d" %>
<% end %>
views/users/_unfollow.html.erb
<%= form_tag "/unfollow", method: :delete , remote: true do %>
<div><%= hidden_field_tag :user_id, @user.id %></div>
<%= submit_tag "Unfollow", data: {disable_with: 'Unfollow...'}, class: "btn btn-d" %>
<% end %>
views/users/show.html.erb
<% if current_user == @user %>
<%= render 'follow_form' %>
<% end %>
我使用 ruby '2.5.0', rails, '5.2.2', mongoid '7.0.2' 并设计
我尝试添加跟随功能,但我在 mongoid '7.0.2' 中出现此错误
message: Ambiguous relations
@options={:class_name=>"User"}, @extension=nil, @module_path="", @polymorphic=false, @default_foreign_key_field="follower_id", @foreign_key="follower_id", @indexed=false, @class_name="User", @klass=User, @validate=false>,
@options={:class_name=>"User"}, @extension=nil, @module_path="", @polymorphic=false, @default_foreign_key_field="followed_id", @foreign_key="followed_id", @indexed=false, @class_name="User", @klass=User, @validate=false> defined on Relationship. summary: When Mongoid attempts to set an inverse document of a relation in memory, it needs to know which relation it belongs to. When setting :relationships, Mongoid looked on the class User for a matching relation, but multiples were found that could potentially match:
@options={:class_name=>"User"}, @extension=nil, @module_path="", @polymorphic=false, @default_foreign_key_field="follower_id", @foreign_key="follower_id", @indexed=false, @class_name="User", @klass=User, @validate=false>,
@options={:class_name=>"User"}, @extension=nil, @module_path="", @polymorphic=false, @default_foreign_key_field="followed_id", @foreign_key="followed_id", @indexed=false, @class_name="User", @klass=User, @validate=false>. resolution: On the :relationships relation on User you must add an :inverse_of option to specify the exact relationship on Relationship that is the opposite of :relationships.
user.rb
class User
include Mongoid::Document
field :email, type: String, default: ""
has_many :relationships, foreign_key: "follower_id", dependent: :destroy
has_many :reverse_relationships, foreign_key: "followed_id", class_name: "Relationship", dependent: :destroy
def retrieve_users_for_ids(user_ids)
users = []
User.in(id: user_ids).each do |user|
users << user
end
users
end
def followed_users
user_ids = []
relationships.each do |relationship|
user_ids << relationship.followed_id
end
return retrieve_users_for_ids(user_ids)
end
def followers
user_ids = []
reverse_relationships.each do |relationship|
user_ids << relationship.follower_id
end
return retrieve_users_for_ids(user_ids)
end
def following?(other_user)
relationships.where(followed_id: other_user.id).first
end
def follow!(other_user)
relationships.create!(followed_id: other_user.id)
end
def unfollow!(other_user)
relationships.where(followed_id: other_user.id).first.destroy
end
end
_follow.html.erb
<%= form_for(current_user.relationships.build(followed_id: @user.id),
remote: true) do |f| %>
<%= f.hidden_field :followed_id %>
<%= f.submit 'Follow', data: {disable_with: 'Follow...'}, class: 'btn btn-d' %>
<% end %>
找到可行的解决方案
user.rb
class User
include Mongoid::Document
has_and_belongs_to_many :following, class_name: 'User', inverse_of: :followers
has_and_belongs_to_many :followers, class_name: 'User', inverse_of: :following
def follow(other_user)
self.following << other_user
other_user.followers << self
end
def unfollow(other_user)
self.following.delete(other_user)
other_user.followers.delete(self)
end
def following?(other_user)
self.following.include?(other_user)
end
end
users_controller.rb
class UsersController < ApplicationController
def following
@title = 'Following'
@user = User.find(params[:id])
@users = @user.following.page(params[:page])
render 'show_follow'
end
def followers
@title = 'Followers'
@user = User.find(params[:id])
@users = @user.followers.page(params[:page])
render 'show_follow'
end
end
relationships_controller.rb
class RelationshipsController < ApplicationController
def create
@user = User.find(params[:user_id])
current_user.follow(@user)
respond_to do |format|
format.html { redirect_to @user }
format.js
end
end
def destroy
@user = User.find(params[:user_id])
current_user.unfollow(@user)
respond_to do |format|
format.html { redirect_to @user }
format.js
end
end
end
routes.rb
Rails.application.routes.draw do
resources :users do
member do
get :following, :followers
end
end
post '/follow/', to: 'relationships#create'
delete '/unfollow', to: 'relationships#destroy'
end
views/relationships/create.js.erb
$("#follow_form").html("<%= escape_javascript(render('users/unfollow')) %>")
$("#followers").html('<%= @user.followers.count %>')
views/relationships/destroy.js.erb
$("#follow_form").html("<%= escape_javascript(render('users/follow')) %>")
$("#followers").html('<%= @user.followers.count %>')
views/users/_follow_form.html.erb
<% unless current_user?(@user) %>
<div id="follow_form">
<% if current_user.following?(@user) %>
<%= render 'unfollow' %>
<% else %>
<%= render 'follow' %>
<% end %>
</div>
<% end %>
views/users/_follow.html.erb
<%= form_tag "/follow", method: :post , remote: true do %>
<%= hidden_field_tag :user_id, @user.id %>
<%= submit_tag "Follow", data: {disable_with: 'Follow...'}, class: "btn btn-d" %>
<% end %>
views/users/_unfollow.html.erb
<%= form_tag "/unfollow", method: :delete , remote: true do %>
<div><%= hidden_field_tag :user_id, @user.id %></div>
<%= submit_tag "Unfollow", data: {disable_with: 'Unfollow...'}, class: "btn btn-d" %>
<% end %>
views/users/show.html.erb
<% if current_user == @user %>
<%= render 'follow_form' %>
<% end %>