7

Sto cercando di seguire questo tutorial su coderwall su Creating a Scoped Invitation System for Rails.Rails 4: metodo non definito `relation_delegate_class 'per Modello: Classe

Nei miei Rails 4 app, ho i seguenti modelli:

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 

Ecco la corrispondenza tra i miei modelli e le modelle dal tutorial:

  • User < =>User
  • Calendar < =>UserGroup
  • Administration < =>Membership
  • Invite < =>Invite

Sono ora nel Fare una nuova sezione Invito:

  • Il modello Invite è stato aggiornato con il filtro before_create e generate_token metodo.
  • Il controller Invites è stato aggiornato con l'azione create.

Tuttavia, quando visito la vista del calendario Modifica per compilare il modulo Invita, ottengo il seguente errore:

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

Il problema sembra provenire dalla linea @invite = @calendar.invites.build.

-----

UPDATE: qui è il contenuto del mio modello Invita:

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 

-----

UPDATE 2: in this question, l'autore spiega che il problema potrebbe provenire da CanCanCan & Rolify. Non uso queste gemme, ma uso Pundit. Ho pensato che sarebbe stato utile nel contesto della mia domanda.

-----

UPDATE 3: qui è anche la migrazione che ho usato per il modello 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 

Mi chiedo se il problema potrebbe essere causato dal t.string :recipient_role, poiché il role di un dato user esiste solo nella tabella administration, per un dato calendar: se :recipient_role viene interpretato automaticamente come recipient.role da Rails, quindi forse th sta causando l'errore?

-----

AGGIORNAMENTO 4: qui è il contenuto della 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 

-----

UPDATE 5: qui sono il server registri:

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/[email protected]/gems/actionpack-4.2.2/lib/action_dispatch/middleware/templates/rescues/_source.erb (6.0ms) 
    Rendered /Users/TXC/.rvm/gems/[email protected]/gems/actionpack-4.2.2/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb (2.8ms) 
    Rendered /Users/TXC/.rvm/gems/[email protected]/gems/actionpack-4.2.2/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb (1.7ms) 
    Rendered /Users/TXC/.rvm/gems/[email protected]/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) 

-----

UPDATE 6: Ho appena realizzato che non avevo

def invite_params 
    params.require(:invite) 
end 

nel controller Invites: potrebbe essere questa la radice del problema qui?

-----

Qualche idea su ciò che significa questo messaggio di errore e su come risolvere il problema?

+1

Puoi mostrare il backtrace completo dell'errore che ottieni? Sarebbe anche utile se riesco a vedere i contenuti del tuo CalendarsController. Grazie. –

+0

Certo, ho appena aggiunto il codice completo di "CalendarsController' e i log del server. Fammi sapere se hai bisogno di ulteriori informazioni. –

+1

Non vedo nulla di ovvio. Prova ad aggiornare tutte le tue gemme. Prova a codificare un nome di classe sull'associazione 'invites'. Prova a commentare tutte le associazioni e poi decommentale una alla volta fino a quando non si rompe. –

risposta

13

Il problema era difficile da identificare, soprattutto dal contenuto della domanda.

IL PROBLEMA

Il motivo per cui mi è stato sempre l'errore è dovuto al fatto undefined method 'relation_delegate_class' for Invite:ClassInvite non è più stato considerato di essere un modello da Rails.

LA RADICE causa del problema

Quando ho creato il Invite mailer, mi sono imbattuto rails g mailer Invite invece di rails g mailer InviteMailer.

A causa di questo, Invite come un programma di posta sostituisce Invite come un modello, creando quindi errori non appena i metodi sono stati applicati alle istanze del modello Invite.

COME abbiamo capito

Uno dei miei amici, che è il modo più esperienza con la programmazione di me, identificato il problema modificando la linea @invite = @calendar.invites.build che stava causando l'errore.

Questo ci ha portato alla fine a eseguire Invite.first nella console di rotaie: mentre dovremmo avere o un'istanza della classe Invite o nil, abbiamo effettivamente ricevuto un errore.

Poiché .first dovrebbe essere un metodo valido su qualsiasi modello di ActiveRecord, ci siamo resi conto che Invite non era considerato un modello di Rails.

COME fisso IT

Una volta che avevamo individuato il problema, fissandola era abbastanza semplice:

  • abbiamo cambiato il nome del Invite mailer invite.rb-invite_mailer.rb
  • Nel file invite_mailer.rb appena rinominato, abbiamo sostituito class Invite < ApplicationMailer con class InviteMailer < ApplicationMailer

Spero che questo possa essere utile ad altri utenti di Stack Overflow che potrebbero ottenere un errore simile relation_delegate_class.

+0

buon lavoro Thibaud Clement! –

+0

Grazie mille K M Rakibul Islam. Ci è voluto del tempo ma l'abbiamo risolto! –

+1

Eseguito nello stesso identico problema con un mailer chiamato invite. Grazie per la risposta dettagliata e per avermi risparmiato un po 'di tempo. –

Problemi correlati