我正在尝试遵循有关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 User
  • Calendar UserGroup
  • Administration Membership
  • Invite Invite

  • 我现在位于“发出新邀请”部分:
  • 已使用Invite过滤器和before_create方法更新了generate_token模型。
  • 已使用Invites操作更新了create Controller 。

  • 但是,当我访问“日历”编辑 View 以填写“邀请”表单时,出现以下错误:
    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&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引起,因为对于给定的role,给定useradministration仅存在于calendar表中:如果rails自动将:recipient_role解释为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 Controller 中:这可能是问题的根源吗?

    ——————

    是否知道此错误消息的含义以及如何解决此问题?

    最佳答案

    很难特别是仅从问题内容中识别问题。

    问题

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

    问题的根本原因

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

    因此,作为邮件程序的Invite会替代Invite作为模型,因此,一旦将方法应用于Invite模型的实例,就会产生错误。

    我们如何计算出

    我的一位比我更富有编程经验的 friend 通过调整导致错误的@invite = @calendar.invites.build行识别了问题。

    这最终导致我们最终在rails控制台中运行Invite.first:尽管我们应该获得Invite类的实例或nil,但实际上却出现了错误。

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

    我们如何修复

    一旦我们确定了问题,就可以很容易地解决它:

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

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

    关于ruby-on-rails - Rails 4 : undefined method `relation_delegate_class' for Model:Class,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/32570689/

    10-10 17:21