Rails 4:未定义的方法`relation_delegate_class'对于Model:Class

时间:2015-09-14 17:41:23

标签: ruby-on-rails ruby-on-rails-4 activerecord model-view-controller nomethoderror

我正在尝试关注 Creating a Scoped Invitation System for Rails 的coderwall教程。

在我的Rails 4应用程序中,我有以下模型:

class User < ActiveRecord::Base
  has_many :administrations
  has_many :calendars, through: :administrations
  has_many :invitations, :class_name => "Invite", :foreign_key => 'recipient_id'
  has_many :sent_invites, :class_name => "Invite", :foreign_key => 'sender_id'
end

class Calendar < ActiveRecord::Base
  has_many :administrations
  has_many :users, through: :administrations
  has_many :invites
end

class Administration < ActiveRecord::Base
  belongs_to :user
  belongs_to :calendar
end

class Invite < ActiveRecord::Base
  belongs_to :calendar
  belongs_to :sender, :class_name => 'User'
  belongs_to :recipient, :class_name => 'User'
end

以下是我的模型与教程中的模型之间的对应关系:

  • User&lt; =&gt; User
  • Calendar&lt; =&gt; UserGroup
  • Administration&lt; =&gt; Membership
  • Invite&lt; =&gt; Invite

我现在正在发表新邀请部分:

  • Invite模型已使用before_create过滤器和generate_token方法进行了更新。
  • Invites控制器已使用create操作进行了更新。

但是,当我访问日历编辑视图以填写邀请表单时,我收到以下错误:

NoMethodError in CalendarsController#edit
undefined method `relation_delegate_class' for Invite:Class
def edit
  @user = current_user
  @invite = @calendar.invites.build
  authorize @calendar
end

问题似乎来自@invite = @calendar.invites.build行。

- - - -

更新:这是我的邀请模型的内容:

class Invite < ActiveRecord::Base
  belongs_to :calendar
  belongs_to :sender, :class_name => 'User'
  belongs_to :recipient, :class_name => 'User'

  before_create :generate_token

  def generate_token
   self.token = Digest::SHA1.hexdigest([self.calendar_id, self.recipient_role, Time.now, rand].join)
  end

end

- - - -

更新2 :在this question中,作者解释说问题可能来自CanCanCan&amp; Rolify。我没有使用这些宝石,但我使用的是Pundit。认为这在我的问题中是有用的。

- - - -

更新3 :这也是我用于Invite模型的迁移:

class CreateInvites < ActiveRecord::Migration
  def change
    create_table :invites do |t|
      t.string :email 
      t.integer :calendar_id
      t.integer :sender_id
      t.integer :recipient_id
      t.string :recipient_role
      t.string :token
      t.timestamps null: false
    end
  end
end

我想知道问题是否可能由t.string :recipient_role引起,因为给定role的{​​{1}}仅存在于user表中,对于给定的{ {1}}:如果administration被Rails自动解释为calendar,那么这可能导致错误吗?

- - - -

更新4 :这是CalendarsController的内容:

:recipient_role

- - - -

更新5 :这是服务器日志:

recipient.role

- - - -

更新6 :我刚才意识到我没有

class CalendarsController < ApplicationController
  before_action :set_calendar, only: [:show, :edit, :update, :destroy]
  before_action :authenticate_user!

  # GET /calendars
  # GET /calendars.json
  def index
    @user = current_user
    @calendars = @user.calendars.all
  end

  # GET /calendars/1
  # GET /calendars/1.json
  def show
    @user = current_user
    @calendar = @user.calendars.find(params[:id])
    authorize @calendar
  end

  # GET /calendars/new
  def new
    @user = current_user
    @calendar = @user.calendars.new
    authorize @calendar
  end

  # GET /calendars/1/edit
  def edit
    @user = current_user
    @invite = @calendar.invites.build
    authorize @calendar
  end

  # POST /calendars
  # POST /calendars.json
def create
  @user = current_user
  @calendar = @user.calendars.create(calendar_params)
  authorize @calendar
  respond_to do |format|
    if @calendar.save
      current_user.set_default_role(@calendar.id, 'Owner')
      format.html { redirect_to calendar_path(@calendar), notice: 'Calendar was successfully created.' }
      format.json { render :show, status: :created, location: @calendar }
    else
      format.html { render :new }
      format.json { render json: @calendar.errors, status: :unprocessable_entity }
    end
  end
end

  # PATCH/PUT /calendars/1
  # PATCH/PUT /calendars/1.json
  def update
    @user = current_user
    @calendar = Calendar.find(params[:id])
    authorize @calendar
    respond_to do |format|
      if @calendar.update(calendar_params)
        format.html { redirect_to calendar_path(@calendar), notice: 'Calendar was successfully updated.' }
        format.json { render :show, status: :ok, location: @calendar }
      else
        format.html { render :edit }
        format.json { render json: @calendar.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /calendars/1
  # DELETE /calendars/1.json
  def destroy
    @user = current_user
    @calendar.destroy
    authorize @calendar
    respond_to do |format|
      format.html { redirect_to calendars_url, notice: 'Calendar was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_calendar
      @calendar = Calendar.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def calendar_params
      params.require(:calendar).permit(:name)
    end
end
Started GET "/calendars/2/edit" for ::1 at 2015-09-14 11:44:13 -0700 Processing by CalendarsController#edit as HTML Parameters: {"id"=>"2"} Calendar Load (0.1ms) SELECT "calendars".* FROM "calendars" WHERE "calendars"."id" = ? LIMIT 1 [["id", 2]] User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT 1 [["id", 1]] Completed 500 Internal Server Error in 3ms (ActiveRecord: 0.3ms) NoMethodError (undefined method `relation_delegate_class' for Invite:Class): app/controllers/calendars_controller.rb:30:in `edit' Rendered /Users/TXC/.rvm/gems/ruby-2.2.1@global/gems/actionpack-4.2.2/lib/action_dispatch/middleware/templates/rescues/_source.erb (6.0ms) Rendered /Users/TXC/.rvm/gems/ruby-2.2.1@global/gems/actionpack-4.2.2/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb (2.8ms) Rendered /Users/TXC/.rvm/gems/ruby-2.2.1@global/gems/actionpack-4.2.2/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb (1.7ms) Rendered /Users/TXC/.rvm/gems/ruby-2.2.1@global/gems/actionpack-4.2.2/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb within rescues/layout (68.9ms) Rendered /Users/TXC/.rvm/gems/ruby-2.2.1/gems/web-console-2.2.1/lib/web_console/templates/_markup.html.erb (0.5ms) Rendered /Users/TXC/.rvm/gems/ruby-2.2.1/gems/web-console-2.2.1/lib/web_console/templates/_inner_console_markup.html.erb within layouts/inlined_string (0.3ms) Rendered /Users/TXC/.rvm/gems/ruby-2.2.1/gems/web-console-2.2.1/lib/web_console/templates/_prompt_box_markup.html.erb within layouts/inlined_string (0.3ms) Rendered /Users/TXC/.rvm/gems/ruby-2.2.1/gems/web-console-2.2.1/lib/web_console/templates/style.css.erb within layouts/inlined_string (0.3ms) Rendered /Users/TXC/.rvm/gems/ruby-2.2.1/gems/web-console-2.2.1/lib/web_console/templates/console.js.erb within layouts/javascript (39.3ms) Rendered /Users/TXC/.rvm/gems/ruby-2.2.1/gems/web-console-2.2.1/lib/web_console/templates/main.js.erb within layouts/javascript (0.4ms) Rendered /Users/TXC/.rvm/gems/ruby-2.2.1/gems/web-console-2.2.1/lib/web_console/templates/error_page.js.erb within layouts/javascript (0.4ms) Rendered /Users/TXC/.rvm/gems/ruby-2.2.1/gems/web-console-2.2.1/lib/web_console/templates/index.html.erb (94.2ms) 控制器中的

:这可能是问题的根源吗?

- - - -

了解此错误消息的含义以及如何解决此问题?

2 个答案:

答案 0 :(得分:20)

这个问题很难识别,特别是从问题的内容来看。

问题

我收到undefined method 'relation_delegate_class' for Invite:Class错误的原因是因为Invite不再被Rails认为是模型。

问题的根本原因

当我创建Invite邮件程序时,我运行了rails g mailer Invite而不是rails g mailer InviteMailer

因此,Invite作为邮件程序覆盖Invite作为模型,因此只要将方法应用于Invite模型的实例,就会产生错误。

我们如何制作出

我的一位朋友,比我更熟悉编程,通过调整导致错误的@invite = @calendar.invites.build行来确定问题。

这导致我们最终在rails控制台中运行Invite.first:虽然我们应该有Invite类的实例,或者nil,但实际上我们遇到了错误。

由于.first应该是任何ActiveRecord模型的有效方法,我们意识到Invite并不被Rails视为模型。

我们如何修复

一旦我们确定了问题,修复它就非常简单了:

  • 我们将Invite邮件的名称从invite.rb更改为invite_mailer.rb
  • 在新重命名的invite_mailer.rb文件中,我们将class Invite < ApplicationMailer替换为class InviteMailer < ApplicationMailer

我希望这对可能会出现类似relation_delegate_class错误的其他Stack Overflow用户有用。

答案 1 :(得分:0)

如果您忘记从ActiveRecord继承模型,也会发生这种情况。 因此,它变成了一个简单的红宝石类。

class MyPlainModel
end