麻烦关注多个实体Rails 5

时间:2022-10-03 00:14:28

I am new to Rails. I'm having an issue where I am trying to follow a list of users and businesses. I had it working at one point but once I added the MVC for businesses I could no longer follow users, but now I can follow businesses. Any ideas would help me....sadly I've tried fixing this issue for hours...

我是Rails的新手。我有一个问题,我正在尝试关注用户和业务列表。我曾经有过一段时间的工作,但是一旦我为业务添加了MVC,我再也无法关注用户,但现在我可以关注业务了。任何想法都会对我有所帮助....遗憾的是,我已经尝试了几个小时解决这个问题......

MY ERROR:


    Started POST "/relationships" for 104.162.78.154 at 2018-04-05 00:57:27 +0000
Processing by RelationshipsController#create as JS
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"aForD+VWaioDYY7MwW8cmMoV/3W09VE/fvpJ1GSbRvTqmI17pVZtoWL/coW0QaUKy10qam60FiaqOfNVScFt4w==", "followed_id"=>"5", "commit"=>"Follow"}
  User Load (0.5ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
  User Load (0.3ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 5], ["LIMIT", 1]]
   (0.1ms)  begin transaction
  CACHE User Load (0.0ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
  User Load (0.3ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 5], ["LIMIT", 1]]
   (0.1ms)  commit transaction
  Rendering relationships/create.js.erb
  Relationship Load (0.3ms)  SELECT  "relationships".* FROM "relationships" WHERE "relationships"."follower_id" = ? AND "relationships"."followed_id" = ? LIMIT ?  [["follower_id", 1], ["followed_id", 5], ["LIMIT", 1]]
  Rendered users/_unfollow.html.erb (3.9ms)
  Rendered relationships/create.js.erb (5.9ms)
Completed 500 Internal Server Error in 22ms (ActiveRecord: 1.7ms)



ActionView::Template::Error (First argument in form cannot contain nil or be empty):
    1: <%= form_for(current_user.active_relationships.find_by(followed_id: @user.id),
    2:              html: { method: :delete },
    3:              remote: true) do |f| %>
    4:   <%= f.submit "Unfollow", class: "btn" %>

app/views/users/_unfollow.html.erb:1:in `_app_views_users__unfollow_html_erb__972617426600285045_69864321826040'
app/views/relationships/create.js.erb:1:in `_app_views_relationships_create_js_erb__1827435763454317283_16594120'
Started POST "/relationships" for 104.162.78.154 at 2018-04-05 01:15:50 +0000
Processing by RelationshipsController#create as JS
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"aForD+VWaioDYY7MwW8cmMoV/3W09VE/fvpJ1GSbRvTqmI17pVZtoWL/coW0QaUKy10qam60FiaqOfNVScFt4w==", "followed_id"=>"5", "commit"=>"Follow"}
  User Load (0.9ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
  User Load (0.4ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 5], ["LIMIT", 1]]
   (0.2ms)  begin transaction
  CACHE User Load (0.0ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
  User Load (0.5ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 5], ["LIMIT", 1]]
   (0.2ms)  commit transaction
  Rendering relationships/create.js.erb
  Relationship Load (0.6ms)  SELECT  "relationships".* FROM "relationships" WHERE "relationships"."follower_id" = ? AND "relationships"."followed_id" = ? LIMIT ?  [["follower_id", 1], ["followed_id", 5], ["LIMIT", 1]]
  Rendered users/_unfollow.html.erb (12.4ms)
  Rendered relationships/create.js.erb (16.2ms)
Completed 500 Internal Server Error in 57ms (ActiveRecord: 2.9ms)

MY CODE:

我的代码:

    class User < ApplicationRecord

  attr_accessor :remember_token, :activation_token, :reset_token
  has_many :experiences
  has_many :reviews, dependent: :destroy
  belongs_to :follower, class_name: "User", optional: true
  belongs_to :followed, class_name: "User", optional: true
  belongs_to :followerz, class_name: "Business", optional: true
  belongs_to :followedz, class_name: "Business", optional: true

  has_many :active_relationships, class_name:  "Relationship",
                                  foreign_key: "follower_id",
                                  dependent:   :destroy
  has_many :passive_relationships, class_name:  "Relationship",
                                   foreign_key: "followed_id",
                                   dependent:   :destroy
  has_many :following, through: :active_relationships,  source: :followed
  has_many :followers, through: :passive_relationships, source: :follower

  has_many :active_relationshipzs, class_name: "Relationshipz",
                                  foreign_key: "followerz_id",
                                  dependent:   :destroy
  has_many :followingz, through: :active_relationshipzs, source: :followedz

  has_many :passive_relationshipzs, class_name:  "Relationshipz",
                                   foreign_key: "followedz_id",
                                   dependent:   :destroy
  has_many :followerzs, through: :passive_relationshipzs, source: :followerz


  before_save   :downcase_email
  before_create :create_activation_digest
  validates :name,  presence: true, length: { maximum: 50 }
  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
  validates :email, presence: true, length: { maximum: 255 },
                    format: { with: VALID_EMAIL_REGEX },
                    uniqueness: { case_sensitive: false }
  has_secure_password
  validates :password, presence: true, length: { minimum: 6 }, allow_nil: true

  # Returns the hash digest of the given string.
  def User.digest(string)
    cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST :
                                                  BCrypt::Engine.cost
    BCrypt::Password.create(string, cost: cost)
  end

  # Returns a random token.
  def User.new_token
    SecureRandom.urlsafe_base64
  end

  # Remembers a user in the database for use in persistent sessions.
  def remember
    self.remember_token = User.new_token
    update_attribute(:remember_digest, User.digest(remember_token))
  end

  # Returns true if the given token matches the digest.
  # Returns true if the given token matches the digest.
  def authenticated?(attribute, token)
    digest = send("#{attribute}_digest")
    return false if digest.nil?
    BCrypt::Password.new(digest).is_password?(token)
  end

  # Forgets a user.
  def forget
    update_attribute(:remember_digest, nil)
  end

  # Activates an account.
  def activate
    update_columns(activated: true, activated_at: Time.zone.now)
  end

  # Sends activation email.
  def send_activation_email
    UserMailer.account_activation(self).deliver_now
  end

  def create_reset_digest
    self.reset_token = User.new_token
    update_columns(reset_digest:  User.digest(reset_token), 
                   reset_sent_at: Time.zone.now)
  end

  # Sends password reset email.
  def send_password_reset_email
    UserMailer.password_reset(self).deliver_now
  end

  # Returns true if a password reset has expired.
  def password_reset_expired?
    reset_sent_at < 2.hours.ago
  end

  def feed
    following_ids = "SELECT followed_id FROM relationships
                     WHERE  follower_id = :user_id"
    Review.where("user_id IN (#{following_ids})
                     OR user_id = :user_id", user_id: id)
    #Review.where("user_id IN (?) OR user_id = ?", following_ids, id)

    #followingz_ids = "SELECT followedz_id FROM relationshipsz
     #                WHERE  followerz_id = :business_id"
   Experience.where("business_id IN (?) OR business_id = ?", followingz_ids, id)
   #Experience.where("business_id IN (#{followingz_ids})
    #                 OR user_id = :user_id", user_id: id)                 
  end

  # Follows a user.
  def follow(other_user)
    active_relationships.create(followed_id: other_user.id)
    #following << other_user
  end

  # Unfollows a user.
  def unfollow(other_user)
    following.delete(other_user)
  end

  # Returns true if the 
 # user is following the other user.
  def following?(other_user)
    following.include?(other_user)
  end



  # Follows a Business.
  def followz(other_business)
   # followingz << other_business

    active_relationshipzs.create(followedz_id: other_business.id)
  end

  # Unfollows a business.
  def unfollowz(other_business)
    followingz.delete(other_business)
  end

  # Returns true if the current user is following the other user.
  def followingz?(other_business)
    followingz.include?(other_business)
  end



  private

    # Converts email to all lower-case.
    def downcase_email
      email.downcase!
    end

    # Creates and assigns the activation token and digest.
    def create_activation_digest
      self.activation_token  = User.new_token
      self.activation_digest = User.digest(activation_token)
    end
end

class UsersController < ApplicationController
  before_action :logged_in_user, only: [:index, :edit, :update, :destroy,
                                        :following, :followers]
  before_action :correct_user,   only: [:edit, :update]
  before_action :admin_user,     only: :destroy

  def index
    @users = User.where(activated: true).paginate(page: params[:page])
    @users = User.paginate(page: params[:user])
  end

    def new
      @user = User.new
    end


  def show
    @user = User.find(params[:id])
    @reviews = @user.reviews.paginate(page: params[:page])
    redirect_to root_url and return unless @user.activated?
  end

  def create
    @user = User.new(user_params)
    if @user.save
      @user.send_activation_email
      flash[:info] = "Please check your email to activate your account."
      redirect_to root_url
    else
      render 'new'
    end
  end


   # Follows a user.
  def follow(other_user)
    following << other_user
  end

  # Unfollows a user.
  def unfollow(other_user)
    following.delete(other_user)
  end

  # Returns true if the current user is following the other user.
  def following?(other_user)
    following.include?(other_user)
  end



  def edit
    @user = User.find(params[:id])
  end

  def update
    if @user.update_attributes(user_params)
      flash[:success] = "Profile updated"
      redirect_to @user
    else
      render 'edit'
    end
  end

  def destroy
    User.find(params[:id]).destroy
    flash[:success] = "User deleted"
    redirect_to users_url
  end

  def following
    @title = "Following"
    @user  = User.find(params[:id])
    @users = @user.following.paginate(page: params[:page])
    render 'show_follow'
  end

  def followers
    @title = "Followers"
    @user  = User.find(params[:id])
    @users = @user.followers.paginate(page: params[:page])
    render 'show_follow'
  end


  private

    def user_params
      params.require(:user).permit(:name, :email, :password,
                                   :password_confirmation)
    end

   #  Confirms a logged-in user.
    def logged_in_user
      unless logged_in?
      store_location
        flash[:danger] = "Please log in."
        redirect_to login_url
      end
    end

    # Confirms the correct user.
    def correct_user
      @user = User.find(params[:id])
      redirect_to(root_url) unless current_user?(@user)
    end

    def admin_user
      redirect_to(root_url) unless current_user.admin?
    end

end

class Relationship < ApplicationRecord
  belongs_to :follower, class_name: "User"
  belongs_to :followed, class_name: "User"
  #validates :follower_id, presence: true
  #validates :followed_id, presence: true

  belongs_to :followerz, class_name: "User"
  belongs_to :followedz, class_name: "Business"
  has_many :active_relationships, class_name:  "Relationship",
                                  foreign_key: "follower_id",
                                  dependent:   :destroy
  has_many :active_relationshipzs, class_name:  "Relationshipz",
                                  foreign_key: "followerz_id",
                                  dependent:   :destroy
end

class RelationshipsController < ApplicationController
  before_action :logged_in_user

  def create
    @user = User.find(params[:followed_id])
    current_user.follow(@user)
    respond_to do |format|
      format.html { redirect_to @user }
      format.js
    end
  end

  def destroy
    @user = Relationship.find(params[:id]).followed
    current_user.unfollow(@user)
    respond_to do |format|
      format.html { redirect_to @user }
      format.js
   end 
  end
end

_follow_form.html.erb

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

_follow.html.erb

_follow.html.erb

<%= form_for(current_user.active_relationships.build, remote: true) do |f| %>
  <div><%= hidden_field_tag :followed_id, @user.id %></div>
  <%= f.submit "Follow", class: "btn btn-primary" %>
<% end %>

_unfollow.html.erb

_unfollow.html.erb

<%= form_for(current_user.active_relationships.find_by(followed_id: @user.id),
             html: { method: :delete },
             remote: true) do |f| %>
  <%= f.submit "Unfollow", class: "btn" %>
<% end %>

create.js.erb

create.js.erb

$("#follow_form").html("<%= escape_javascript(render('users/unfollow')) %>");
$("#followers").html('<%= @user.followers.count %>');

destroy.js.erb

destroy.js.erb

$("#follow_form").html("<%= escape_javascript(render('users/follow')) %>");
$("#followers").html('<%= @user.followers.count %>');

If I had to guess maybe I've been too redundant because for the MVC for the business model which I have not posted...is basically the same thing but I added a "z" to everything(followz...unfollowz....Realtionshipzs...). I am using Cloud9.

如果我不得不猜测也许我太过多了,因为MVC对于我没有发布的商业模式......基本上是一样的但是我给所有东西添加了一个“z”(followz ... unfollowz .. ..Realtionshipzs ...)。我正在使用Cloud9。

1 个解决方案

#1


1  

ActionView::Template::Error (First argument in form cannot contain nil or be empty):
    1: <%= form_for(current_user.active_relationships.find_by(followed_id: @user.id),
    2:              html: { method: :delete },
    3:              remote: true) do |f| %>
    4:   <%= f.submit "Unfollow", class: "btn" %>

If current_user has no active relationship with @user, then your form_for will have a null argument. You should add an if statement, such that if @user is not followed, then you cannot unfollow.

如果current_user与@user没有活动关系,那么form_for将具有null参数。您应该添加一个if语句,这样如果不遵循@user,则无法取消关注。

#1


1  

ActionView::Template::Error (First argument in form cannot contain nil or be empty):
    1: <%= form_for(current_user.active_relationships.find_by(followed_id: @user.id),
    2:              html: { method: :delete },
    3:              remote: true) do |f| %>
    4:   <%= f.submit "Unfollow", class: "btn" %>

If current_user has no active relationship with @user, then your form_for will have a null argument. You should add an if statement, such that if @user is not followed, then you cannot unfollow.

如果current_user与@user没有活动关系,那么form_for将具有null参数。您应该添加一个if语句,这样如果不遵循@user,则无法取消关注。