【问题标题】:Models associated with one another create undefined methods in Rails 5 undefined method `shoutouts' for #<User:0x007fd825472cf0>相互关联的模型在 Rails 5 中为#<User:0x007fd825472cf0> 创建未定义方法“shoutouts”
【发布时间】:2017-02-04 02:23:44
【问题描述】:

正在使用 Michael Harti 的 Ruby on Rails Tutorial 并且在关注它时,我在两个模型之间得到了一个未定义的方法。我已重命名模型并尝试使用它进行了很多尝试,但所有尝试都以未定义的方法或未初始化的常量结束。

喊出控制器

class ShoutOutController < ApplicationController

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

def create
    @shout_out = current_user.shout_out.build(shout_out_params)
    if @shout_out.save
        flash[:success] = "Shout Out Created"
        redirect_to root_url
    else
        render user
    end
end

def destroy
end

private

def shout_out_params
    params.require(:shout_out).permit(:content)
end
end

用户控制器

class UsersController < ApplicationController
  def index
    @users = User.paginate(page: params[:page])
  end
  def new
    @user = User.new
  end

  def show
    @user = User.find(params[:id])
    @shoutouts = @user.shout_outs.paginate(page: params[:page])
    @shoutouts.user = User.find(params[:id]).name
  end

  def create
    @user = User.new(user_params)
    if @user.save
      log_in @user
      flash[:success] = "Welcome!"
      redirect_to @user
    else
      render 'new'
    end
  end

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

  def update
    @user = User.find(params[:id])
    if @user.update_attributes(user_params)
      #handles successful update of account info
      flash[:success] = "Updated Profile Info"
      redirect_to @user
   else
      render 'edit'
   end
 end

private

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

用户模型

class User < ActiveRecord::Base
  attr_accessor :remember_token 
  # :activation_token
  has_many :scrimmages
  has_many :ShoutOuts, dependent: :destroy
  has_many :friendships
  has_many :direct_messages, :through => :friendships
  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 }
  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 for remember function
  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 token matches the digest
  def authenticated?(remember_token)
    return false if remember_digest.nil?
    BCrypt::Password.new(remember_digest).is_password?(remember_token)
  end
  #forgets the user
  def forget
    update_attribute(:remember_digest, nil)
  end

  private

  # converts emails to downcase
  def downcase_email
    self.email = email.downcase
  end
  #creates and assigns activation token and digest
  def create_activation_digest
    self.activation_token = User.new_token
    self.activation_digest = User.digest(activation_token)
  end
end

微博模型

class ShoutOut < ApplicationRecord
  belongs_to :user
  default_scope -> { order(created_at: :desc)}
  validates :user_id, presence: true
  validates :content, presence: true, length: {maximum: 140}
end

查看部分

<li id="shoutout-<%= ShoutOut.id %>">
<%= link_to gravatar_for(ShoutOut.user, size: 50), ShoutOut.user %>
<span class="user"><%= link_to ShoutOut.user.name, ShoutOut.user %></span>
<span class="content"><%= ShoutOut.content %></span>
<span class="timestamp">
    Posted <%= time_ago_in_words(shout_out.created_at) %> ago.
</span>

路由文件

Rails.application.routes.draw do

  # root to: 'users#new'
  # these routes are for showing users a login form, logging them in, and logging them out.
   get '/login' => 'sessions#new'
   post '/login' => 'sessions#create'
   get '/logout' => 'sessions#destroy'

  get '/signup' => 'users#new'
  post '/users' => 'users#create'
  post '/users/id/edit' => 'users#edit'

  resources :users
  resources :account_activations, only: [:edit]
  root to: 'landing#index'
end

Error Message Screenshot-

【问题讨论】:

  • 请发布错误信息。
  • 欢迎来到 Stack Overflow!寻求调试帮助的问题(“为什么这段代码不起作用?”)必须包括所需的行为、特定问题或错误重现它所需的最短代码在问题本身。没有明确问题陈述的问题对其他读者没有用处。请参阅:How to create a Minimal, Complete, and Verifiable example

标签: ruby-on-rails


【解决方案1】:

上面的代码中有几个错误让rails感到困惑。

  1. 在 micropost 模型中,您定义了一个名为 ShoutOut 的类。您可能听说过“约定优于配置”的说法。 Rails 正在寻找喊出文件。您的 ShoutOut 类应位于模型文件夹中名为shout_out.rb 的文件中。
  2. 在用户类中,你放了has_many ShoutOuts,应该是has_many :shout_outs
  3. 我感觉 ShoutOutController 应该是 ShoutOutsController,但您需要发布您的路由文件才能确认。
  4. 在部分视图中,为什么调用 ShoutOut.id?我怀疑您想使用shout_out.id,但您需要发布调用该部分的视图以及调用该视图的控制器方法。在此视图中,您当前只能访问在用户控制器的 show 方法中设置的 @user 变量。

您似乎不清楚为什么有些东西应该大写以及为什么不应该大写。阅读实例与方法变量以及类方法与实例方法。在您的视图中尝试以下操作

<% @user.shoutouts.each do |shout_out| %>
  <li id="shoutout-<%= shout_out.id %>">
    <%= link_to gravatar_for(@user, size: 50), @user %>
    <span class="user"><%= link_to @user.name, @user %></span>
    <span class="content"><%= shout_out.content %></span>
    <span class="timestamp"> Posted <%= time_ago_in_words(shout_out.created_at) %> ago. </span>
  </li>
<% end %>

正如 Joe C 评论的那样,您需要将实际的错误消息与堆栈跟踪一起发布,以便我们可以帮助您调试错误。如果您仔细查看错误消息,它将为您提供错误发生位置的文件名和行号。

【讨论】:

  • 感谢您的帮助,margo,1)我确实将文件列为shout_out.rb 2)我已将关联编辑回:shout_outs,但仍然收到无方法错误3)我有在上面发布了路由文件,并在屏幕上显示了错误,部分内容正在 User#show 上呈现,并且控制器在上面列出
  • 您似乎不了解从控制器操作传递变量以在视图中使用。在 Users#show 中,您只设置了一个 @user 变量,因此这是您可以在显示视图中使用的唯一变量。您收到该错误是因为您正在使用类 Shout 并且它没有类方法“id”。我会用一些代码修改我的答案,供您在视图中尝试。
【解决方案2】:

Ty 再次提供帮助,但我一直使用的是上面链接的 michael harti 的指南,经过大量更改后,我决定在 Stack 上发帖。我尝试使用 User.shout_outUser.shoutoutUser.shout_outs 结果是相同的错误。指南错了吗?

【讨论】:

  • 我无法对指南发表评论,但您是否尝试过我在下面发布的代码。另外,我认为您不需要在 UsersController 的显示操作中使用第二和第三行。
  • 我尝试了您在上面发布的编辑,我收到了以下错误 link 我还尝试删除 @user 并离开用户并使用 gravatar @987654322 的帮助文件得到以下错误@.
  • 再次,我敦促您使用错误消息中的信息。它说给出了 2 个参数,预期 1 个。在您的链接中删除第二个参数(大小:50)。关于第二个,使用 @user 并阅读如何将变量从控制器传递到视图,根据我上面的评论。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多