My tests pass. But, the undefined `` reviews '' method for nil: NilClass when the page is called

Good afternoon people

I am trying to create a tobacco viewing application, for nothing but to learn more. I tried to use what Ive learned in the Rails Tutorial, however, I always run into brick walls and grills that I don’t understand. I can normally overcome the undefined `something 'method for nil: NilClass and the other problems that I have, but it really causes me a dead end because Ive got my tests.

My tests

review_test.rb

require 'test_helper' class ReviewTest < ActiveSupport::TestCase # Define a user for the test def setup @user = users(:shaun) @review = @user.reviews.build( rating: 5, comment:"This is a super snus", tobacco_id: 1) end # Test should be valid test "should be valid" do assert @review.valid? end # Test the user id is present test "user id should be present" do @review.user_id = nil assert_not @review.valid? end # Test the tobacco id is present test "tobacco id should be present" do @review.tobacco_id = nil assert_not @review.valid? end # Rating should be present test "rating should be present" do @review.rating = " " assert_not @review.valid? end # Comment should be present test "comment should be present" do @review.comment = " " assert_not @review.valid? end # Verify that the first review in the DB is the same as fixture review test "order should be most recent first" do assert_equal reviews(:most_recent), Review.first end end 

user_test.rb

 # Test that a review is destroyed when a user is destroyed test "associated reviews should be destroyed" do @user.save @user.reviews.create!( rating: 5, comment: "I love this suns, it so good!", tobacco_id: 1) assert_difference 'Review.count', -1 do @user.destroy end end 

Fixtures

reviews.yml

 one: rating: 5 tobacco_id: 1 comment: "This is a super snus" created_at: <%= 3.hours.ago %> two: rating: 5 tobacco_id: 1 comment: "This is the best snus in the world" created_at: <%= 2.hours.ago %> three: rating: 5 tobacco_id: 1 comment: "I will always buy this snus" created_at: <%= 1.hours.ago %> most_recent: rating: 5 tobacco_id: 1 comment: "I have a shed load of this snus, it great!" created_at: <%= Time.zone.now %> 

Models

review.rb

 belongs_to :tobacco 

tobacco.rb

 has_many :reviews 

user.rb

 has_many :tobaccos, dependent: :destroy has_many :reviews, dependent: :destroy 

reviews_controller.rb controller

 def new @review = Review.new end 

This is what I have for the create action in the controller, but I can’t say if I have it right, because I can’t load the page yet. Any suggestions for creating an action would be very helpful if I asked another question, if I have it wrong, which I probably have!

 def create @tobacco = Tobacco.find(params[:tobacco_id]) @review = @tobacco.reviews.new(params[:review].permit(:tobacco_id, :comment)) @review.user = User.find(current_user.id) @review.save redirect_to tobacco_path(@tobacco) end 

Routes

 resources :tobaccos do resources :reviews, except: [:show, :index] end 

show.html.erb

 <%= link_to "Write a Review", new_tobacco_review_path(@tobacco) %> 

new.html.erb

 <%= form_for([@tobacco, @tobacco.reviews.build]) do |f| %> <%= render 'fields', f: f %> <%= f.submit "Save Review", class: 'btn btn-primary' %> <% end %> 

When I go to the page to write a review, I get an error

 Showing C:/Sites/apps/review/app/views/reviews/new.html.erb where line #11 raised: undefined method `reviews' for nil:NilClass 

That tells me it's line 11

 <%= form_for([@tobacco, @tobacco.reviews.build]) do |f| %> 

but all that I try, I get another error. I know this is a rookie mistake, but I don't see it.

Thank you in advance

Sean

UPDATE

I have work and save in the database now, I did it like this In the reviews_controller.rb new and created look like this:

 def new @tobacco = Tobacco.find(params[:tobacco_id]) end def create @tobacco = Tobacco.find(params[:tobacco_id]) @review = Review.new(review_params) @review.user_id = current_user.id @review.tobacco_id = @tobacco.id if @review.save redirect_to @tobacco else render 'new' end end 

Param Overview

 def review_params params.require(:review).permit(:rating, :comment, :tobacco_id) end 

Everything looks right for me, and it works, so I hope everything will be fine.

Now I'm stuck in editing a tobacco review. This is the first time I have worked on nested routes. I just looked at a couple of tutorials, but nothing helped me fix it. I'm not sure how to pass these keys ...

On the show page I have this

 <%= link_to "Edit", edit_tobacco_review_path(@tobacco, @review) %> 

The show tobaccos_controller.rb method looks like this:

 def show @tobacco = Tobacco.find(params[:id]) @reviews = Review.where(tobacco_id: @tobacco.id) end 

In reviews_controller.rb I have this

 def edit @tobacco = Tobacco.find(params[:tobacco_id]) @review = Review.find(params[:id]) end 

And the error I get is

 ActionController::UrlGenerationError in Tobaccos#show No route matches {:action=>"edit", :controller=>"reviews", :id=>nil, :tobacco_id=>"8"} missing required keys: [:id] 

Looking at this, I have to do something in the Tobaccos # show, but I can’t think of that.

I'm almost home and dry, you see what I did wrong? Thanks:)

TWO UPDATE NUMBER show.html.erb This is not an entire page to display, but it is an important part

 <% if @reviews.blank? %> <h3>No reviews yet! Would you like to be the first?</h3> <%= link_to "Write Review", new_tobacco_review_path(@tobacco), class: "btn btn-danger" %> <% else %> <% @reviews.each do |review| %> <div class="reviews"> <p><%= review.comment %></p> <p><%= review.user.name %></p> <%= link_to "Edit", edit_tobacco_review_path(@tobacco, @review) %> </div> <% end %> <%= link_to "Write Another Review", new_tobacco_review_path(@tobacco), class: "btn btn-danger" %> <% end %> 

UPDATE NUMBER 3 edit.html.erb

 <%= form_for([@tobacco, @tobacco.reviews.build]) do |f| %> <%= render 'fields', f: f %> <%= f.submit "Update Review", class: 'btn btn-primary' %> <% end %> <%= link_to "Back", tobacco_path(@tobacco), class: "btn btn-default btn-block margin-top-25" %> 

_fields.html.erb

 <%= f.label :rating %> <%= f.select :rating, [['1', 1], ['2', 2], ['3', 3], ['4', 4], ['5', 5] ] ,class: 'form-control' %> <%= f.label :comment %> <%= f.text_field :comment, class: 'form-control' %> 
+5
source share
1 answer

ActionController :: UrlGenerationError in Tobaccos # show There are no matches in the route {: action => "edit" ,: controller => "reviews" ,: id => nil ,: tobacco_id => "8"} missing required keys: [: id

You repeat @reviews as review , so

this line

 <%= link_to "Edit", edit_tobacco_review_path(@tobacco, @review) %> 

it should be

 <%= link_to "Edit", edit_tobacco_review_path(@tobacco, review) %> 
+2
source

All Articles