2016-12-13 8 views
0
feature "comment" do 
given(:user) do 
     build(:user) 
end 
background do 
    user1=create(:user) 
    user1.id=1 
    login_as(user1)  
end 
scenario "can create comment" do 
    @undertake=create(:undertake) 
    visit undertake_path(@undertake) 
    within("form#undertake-form-test") do 
     fill_in "content" , with: "heyheyhey" 
    end 
    click_button 'send-btn' 
    expect(page).to have_content 'heyheyhey' 
end 
end 

Dies ist spec/features/comment_spec.rb. und das unten ist controllers/intrams_controller.rb.rspec, undefined Methode `id 'für nil: NilClass

class UndertakesController < ApplicationController 
    def show 
    @undertake=Undertake.find_by(id: params[:id]) 
    @comment=current_user.comments.new 
end 

und das unten ist views/assists/show.html.erb.

<p><%= @undertake.id %></p> 

und spec/fabriken/unconsents.rb.

FactoryGirl.define do 
    factory :undertake do 
    association :ask 
    association :user 
    id 1 
    user_id 2 
    ask_id 1 
    title "MyString" 
    content "MyText" 
    result false  
    end 
end 

routes.rb

resources :asks , except:[:edit, :update] do 
    resources :undertakes , only:[:create , :show , :destroy] , shallow: true do 
    resources :comments , only:[:create] 
    end 
end 

Nun, warum habe ich Fehler ActionView::Template::Error:undefined method id for nil:NilClass. Bitte hilf mir.

+0

Bitte zeigen Sie Ihre 'routes.rb' Datei an. –

+0

Hier ist routes.rb. Bitte. –

+0

Ressourcen: fragt, außer: [: edit,: update] do Ressourcen: übernimmt, nur: [: create,: show,: destroy], flach: true do Ressourcen: Kommentare, nur: [: create] Ende Ende –

Antwort

2

Es gibt ziemlich viele Dinge hier, die die mögliche Ursache sein könnten und die sehr unidiomatisch wenn nicht gerade falsch sind.

Zuerst ist der Name undertake ist einfach falsch. Verwenden Sie stattdessen das Nomenformular Undertaking für einen Modellnamen.

Niemals find_by(id: params[:id]) verwenden. Verwenden Sie stattdessen find(params[:id]), da dadurch eine ActiveRecord::RecordNotFoundError ausgelöst wird und die 404-Seite gerendert wird, wenn der Datensatz nicht gefunden wird, anstatt mit einem Null-Fehler in die Luft zu gehen.

class UndertakingsController < ApplicationController 
    def show 
    @undertaking = Undertaking.find(params[:id]) 
    @comment = @undertaking.comments.new 
    end 
end 

Auch sollten Sie den Kommentar von @undertaking erschaffen - nicht den Benutzer-ID über ein Formular übergeben, wie es es Childs macht spielt für einen malicous Benutzer zu fälschen.

Statt den Benutzer aus der Sitzung zuweisen, wenn Datensätze erstellen:

class CommentsController 
    # this assumes you are using Devise 
    before_action :authenticate_user! 
    def create 
    @comment = Comment.new(comment_params) do |c| 
     c.user = current_user 
    end 
    # ... 
    end 
end 

Dies ist, wie Sie die spec idiomatisch schreiben würde. Beachten Sie die Verwendung von memoisierten let Helfern und die Tatsache, dass Sie NEVER IDs zu Datensätzen zuweisen. Das wird von der Datenbank gemacht. Der Versuch, es manuell zu tun, wird die Dinge nur vermasseln.

require 'rails_helper' 
RSpec.describe 'Comments' do 
    let(:current_user) { create(:user) } 
    let(:undertaking) { create(:undertaking) } 

    background do 
    login_as(current_user) 
    end 

    scenario "can create a comment" do 
    visit undertaking_path(undertaking) 
    # Avoid using CSS selectors and instead write specs 
    # based on what the user sees as it makes specs brittle 
    within("form#undertake-form-test") do 
     fill_in "content" , with: "heyheyhey" 
     click_button 'Create comment' 
    end 
    expect(page).to have_content 'heyheyhey' 
    end 
end 

Verwenden let statt @instance Variablen. Wenn Sie Merkmale, Anforderungen und Controller-Spezifikationen schreiben, müssen Sie FactoryGirl.create nicht build verwenden, da der spätere Eintrag nicht in die Datenbank eingefügt wird und der Datensatz in Ihrer Rails-Anwendung nicht existiert.

Auch Ihre Fabrikdefinition ist stark beschädigt. Die ganze Idee einer Fabrik ist, dass sie einzigartige, gültige Aufzeichnungen erstellen sollte. Setzen Sie niemals Ids in einer Fabrik.

FactoryGirl.define do 
    factory :undertaking do 
    title "MyString" 
    content "MyText" 
    user # just reference the factory if you REALLY need the association to exist 
    ask # just reference the factory if you REALLY need the association to exist 
    result false # this should probally be set through a DB default instead! 
    end 
end 
+0

Great advice! :) –

+0

Vielen Dank für Ihre Empfehlung! Ich werde auf diese Weise tun! –

Verwandte Themen