Rails 4:Model:Class的未定义方法`relation_delegate_class’

我正在尝试按照这个关于为Rails创建一个Scoped邀请系统的编码器教程。

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

class User  "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  'User' belongs_to :recipient, :class_name => 'User' end 

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

  • User User
  • Calendar UserGroup
  • Administration Membership
  • Invite Invite

我现在正在制作一个新邀请部分:

  • Invite模型已使用before_createfilter和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  '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 :在这个问题中 ,作者解释了问题可能来自CanCanCan和Rolify。 我不使用这些gem,但我使用的是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引起的,因为给定userrole只存在于administration表中,对于给定的calendar :if :recipient_role被Rails自动解释为recipient.role ,然后也许这是导致错误?

—–

更新4 :这是CalendarsController的内容:

 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 

—–

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

 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) 

—–

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

 def invite_params params.require(:invite) end 

Invites控制器中:这可能是问题的根源吗?

—–

有关此错误消息的含义以及如何解决问题的任何想法?

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

问题

undefined method 'relation_delegate_class' for Invite:Class错误获取undefined method 'relation_delegate_class' for Invite:Class的原因是因为Rails不再将Invite视为模型。

问题的根本原因

当我创建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.rbinvite_mailer.rb
  • 在新重命名的invite_mailer.rb文件中,我们用class InviteMailer < ApplicationMailer替换了class Invite < ApplicationMailer class InviteMailer < ApplicationMailer

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