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_create
filter和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
引起的,因为给定user
的role
只存在于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.rb
为invite_mailer.rb
- 在新重命名的
invite_mailer.rb
文件中,我们用class InviteMailer < ApplicationMailer
替换了class Invite < ApplicationMailer
class InviteMailer < ApplicationMailer
我希望这可能对其他可能获得类似relation_delegate_class
错误的Stack Overflow用户有用。