Why Am I Receiving this NoMethodError? - ruby-on-rails

I am working through a Ruby on Rails tutorial for creating a blog and I have received this error when I go to bring up the page in my localhost:3000 address:
'undefined method `each' for nil:NilClass'
My Controller:
class PostsController < ApplicationController
def new
end
def create
#post = Post.new(params[:post].permit(:title, :text))
#post.save
redirect_to #post
end
def show
#post = Post.find(params[:id])
end
private
def post_params
params.require(:post).permit(:title, :text)
end
def index
#posts = Post.all
end
end
My View File:
<h1>Listing posts</h1>
<table>
<tr>
<th>Title</th>
<th>Text</th>
</tr>
<% #posts.each do |post| %>
<tr>
<td><%= post.title %></td>
<td><%= post.text %></td>
</tr>
<% end %>
</table>
Can someone help me out?

You should move index action away from private section.

Because your PostsController#index method is private, so its code doesn't run when you enter /posts, so #posts instance variable remains nil.
Move it to public section:
class PostsController < ApplicationController
def index
#posts = Post.all
end
def new
end
def create
#post = Post.new(params[:post].permit(:title, :text))
#post.save
redirect_to #post
end
def show
#post = Post.find(params[:id])
end
private
def post_params
params.require(:post).permit(:title, :text)
end
end

Related

undefined method `each' for nil:NilClass. Instance variable doesn't work

<tbody>
<% #articles.each do |article| %>
<tr>
<td><%= article.title %></td>
<td>Some description</td>
<td>Placeholder</td>
</tr>
<% end %>
</tbody>
I defined an instance in controller, but I cannot get it to work in my html.erb.
def index
#articles = Article.all
end
When I change #articles to Article.all - it works.
Can anyone tell me why the instance variable doesn't?
Thanks
Rails.application.routes.draw do
root 'pages#home'
get 'about', to:'pages#about'
resources :articles, only: [:show, :index]
end
class ArticlesController < ApplicationController
def show
#article = Article.find(params[:id])
end
def index
#articles = Article.all
end
def create
#article = Article.new(params.require(:article).permit(:title, :description))
if #article.save
flash[:notice] = "Article was created successfully"
redirect_to #article
else
render 'new'
end
end
def new
#article = Article.new
end
end

Trying to create comments. (Undefined method 'comment')

I am receiving this error and I don't understand as I have defined the method in the comments controller, haven't I?
I am getting slightly confused to why it is not working.
Comments controller:
class CommentsController < ApplicationController
def create
#story = Story.find(params[:story_id])
#comment = #story.comments.create(params[:comment].permit(:name, :body))
redirect_to root_path
end
end
Stories Controller:
class StoriesController < ApplicationController
before_action only: [:destroy, :show, :edit, :update]
def index
#stories = Story.order('created_at DESC')
end
def new
#story = current_user.stories.build
end
def create
#story = current_user.stories.build(story_params)
if #story.save
flash[:success] = "Your beautiful story has been added!"
redirect_to root_path
else
render 'new'
end
end
def edit
#story = Story.find(params[:id])
end
def update
#story = Story.find(params[:id])
if #story.update_attributes(params.require(:story).permit(:name, :description))
flash[:success] = "More knowledge, more wisdom"
redirect_to root_path
else
render 'edit'
end
end
def destroy
#story = Story.find(params[:id])
if #story.destroy
flash[:success] = "I think you should have more confidence in your storytelling"
redirect_to root_path
else
flash[:error] = "Can't delete this story, sorry"
end
end
def show
#stories = Story.all
end
private
def story_params
params.require(:story).permit(:name, :description)
end
end
Index.html.erb:
<p id="notice"><%= notice %></p>
<h1>This is a list of posts</h1>
<table>
<thead>
<tr>
<th>Name</th>
<th>Description</th>
<th>User</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% #stories.each do |story| %>
<tr>
<td><%= story.name %></td>
<td><%= story.description %></td>
<td><%= story.user.username %></td>
<td><%= link_to 'Show', story %></td>
<% if user_signed_in? %>
<td><%= link_to 'Edit', edit_story_path(story)%></td>
<td><%= link_to 'Destroy', story_path(story),method: :delete,data: { confirm: 'Are you sure?' } %></td>
<% end %>
</tr>
</tbody>
</table>
<h2><%= #story.comments.count %>Comments</h2>
<%= render #story.comments %>
<h3>Add a comment</h3>
<%= render 'comments/form' %>
<%= link_to 'New Story', new_story_path %>
Story Controller:
class CommentsController < ApplicationController
before_action :set_comment, only: [:show, :edit, :update, :destroy]
# GET /comments
# GET /comments.json
def index
#comments = Comment.all
end
# GET /comments/1
# GET /comments/1.json
def show
#comments = #story.comments.all
#comment = #stroy.comments.build
end
# GET /comments/new
def new
#comment = Comment.new
end
# GET /comments/1/edit
def edit
end
# POST /comments
# POST /comments.json
def create
#story = Story.find(params[:story_id])
#story.comments.create(comment_params)
end
# PATCH/PUT /comments/1
# PATCH/PUT /comments/1.json
def update
respond_to do |format|
if #comment.update(comment_params)
format.html { redirect_to #comment, notice: 'Comment was successfully updated.' }
format.json { render :show, status: :ok, location: #comment }
else
format.html { render :edit }
format.json { render json: #comment.errors, status: :unprocessable_entity }
end
end
end
# DELETE /comments/1
# DELETE /comments/1.json
def destroy
#comment.destroy
respond_to do |format|
format.html { redirect_to comments_url, notice: 'Comment was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_comment
#comment = Comment.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def comment_params
params.require(:comment).permit(:user_name, :body, :story_id)
end
end
Make sure you have run the right migrations
rails g scaffold comment user_name:string body:text story:references
now
rake db:migrate
In your story model write
has_many :comments
And in your comment model make sure you have
belongs_to :story
or in your story controller in the show method have this
#comments = #story.comments.all
#comment = #stroy.comments.build
And now in your story form show views, something like this
<h3>Comments</h3>
<% #comments.each do |comment| %>
<div>
<p><%= comment.body %></p>
</div>
<% end %>
<%= render 'comments/form' %>
In your comment/_form.html.erb add
<%= f.hidden_field :story_id %>
If you want to display on your index edit you like so
<tbody>
<% #stories.each do |story| %>
<tr>
<td><%= story.name %></td>
<td><%= story.description %></td>
<td><%= story.user.username %></td>
<td><%= link_to 'Show', story %></td>
<% if user_signed_in? %>
<td><%= link_to 'Edit', edit_story_path(story)%></td>
<td><%= link_to 'Destroy', story_path(story),method: :delete,data: { confirm: 'Are you sure?' } %></td>
<% story.comments.each do |c| %>
<%= c.body %>
<% end %>
<% end %>
</tr>
</tbody>
You have to start by understanding how associations works:
One Story will have many comments.
You have to define the association in the model:
class Story < ActiveRecord::Base
has_many :comments
end
class Comment < ActiveRecord::Base
belongs_to :story
end
Then the methods in the controller will be available:
class CommentsController < ApplicationController
def create
#story = Story.find(params[:story_id])
#story.comments.create(comment_params)
end
end
And in your app/stories/show.html.erb view:
<% #story.comments.each do |comment| %>
<%= comment.body #or the comment content method %>
<% end %>

ActionController::UrlGenerationError routing error

I set up a Rails toy to play with Twitter API, but already having challenges right from the start. My files look like this:
routes.rb
Rails.application.routes.draw do
devise_for :users
root to: 'accounts#index'
resources :accounts do
resources :posts
end
end
account.rb
class Account < ActiveRecord::Base
belongs_to :user
has_many :posts
accepts_nested_attributes_for :posts
validates :name, :description, presence: :true
end
post.rb
class Post < ActiveRecord::Base
belongs_to :account
validates :tweet, presence: true
end
accounts_controller.rb
class AccountsController < ApplicationController
before_action :authenticate_user!
def index
#accounts = Account.all
#user = current_user
end
def new
#account = Account.new
end
def create
#account = Account.new(account_params)
#account.user = current_user
if #account.save
flash[:notice] = "Account succesfully created."
redirect_to #account
else
flash.now[:alert] = "Oops, something went wrong!"
render 'new'
end
end
def show
#account = Account.find(params[:id])
end
def update
end
def destroy
end
private
def account_params
params.require(:account).permit(:name, :description, posts_attributes: [:tweet])
end
end
post_controller.rb
class PostsController < ApplicationController
before_action :set_account
def index
#posts = Post.all
end
def new
#post = Post.new
end
def create
#post = #account.posts.build(post_params)
if #post.save
flash[:notice] = "Tweet created successfully."
redirect_to [#account, #post]
else
flash.now[:alert] = "Something went wrong."
render 'new'
end
end
def edit
#post = Post.find(params[:id])
end
def update
if #post.update
flash[:notice] = "Tweet updated."
redirect_to [#account, #post]
else
flash.now[:alert] = "Something is not right!"
render 'edit'
end
end
def destroy
end
def show
#post = Post.find(params[:id])
end
private
def post_params
params.require(:post).permit(:tweet)
end
def set_account
#account = Account.find(params[:account_id])
end
end
The tricky part is here:
What I am trying to do here is on the accounts page, when a user clicks on the account name, he should be redirects to the new action of the Posts controller that will allow him to create a new post for the account in question. Somehow, I am not sure how to pass the :account_id parameter.
views/accounts/index.html.erb
<table>
<tr>
<th>Account Name</th>
<th>Description</th>
<th>Tweets</th>
</tr>
<% #user.accounts.each do |account| %>
<tr>
<td><%= link_to account.name, new_account_post_path(#account) %></td>
<td><%= account.description %></td>
<td><%= account.posts.count %></td>
</tr>
<% end %>
</table>
<%= link_to "Sign out", destroy_user_session_path, :method => :delete %>
<%= link_to "Create new account", new_account_path %>
Error in browser:
You need to change
<%= link_to account.name, new_account_post_path(#account) %>
to
<%= link_to account.name, new_account_post_path(account) %>
Use this code:
<% #user.accounts.each do |account| %>
<tr>
<td><%= link_to account.name, new_account_post_path(account) %></td>
<td><%= account.description %></td>
<td><%= account.posts.count %></td>
</tr>
<% end %>

Ruby getting started guide: uninitialized constant PostsController::Posts

I've done the ruby getting started guide a few times over and I always end up with the same result.
Guids
NameError in PostsController#index
uninitialized constant PostsController::Posts
Extracted source (around line #21):
19
20
21
22
23
24
def index
#posts = Posts.all
end
def edit
Rails.root: C:/RailsTesting/blog
Application Trace | Framework Trace | Full Trace
app/controllers/posts_controller.rb:21:in `index'
Request
Out of frustration/desperation, I copied all of the files from the actual code supplied by the tutorial with no avail, please help.
Here's my index
<h1>Hello, Rails!</h1>
<%= link_to "My Blog", controller: "posts" %>
<%= link_to 'New post', new_post_path %>
<table>
<tr>
<th>Title</th>
<th>Text</th>
<th></th>
<th></th>
</tr>
<% #posts.each do |post| %>
<tr>
<td><%= post.title %></td>
<td><%= post.text %></td>
<td><%= link_to 'Show', post %></td>
<td><%= link_to 'Edit', edit_post_path(post) %></td>
<td><%= link_to 'Destroy', post_path(post),
method: :delete, data: { confirm: 'Are you sure?' } %>
</tr>
...
Here is my posts_controller
class PostsController < ApplicationController
def new
#post = Post.new
end
def create
#post = Post.new(params[:post].permit(:title, :text))
if #post.save
redirect_to #post
else
render 'new'
end
end
def show
#post = Post.find(params[:id])
end
def index
#posts = Posts.all
end
def edit
#post = Post.find(params[:id])
end
def update
#post = Post.find(params[:id])
if #post.update(params[:post].permit(:title, :text))
redirect_to #post
else
render 'edit'
end
end
def destroy
#post = Post.find(params[:id])
#post.destroy
redirect_to posts_path
end
private
def post_params
params.require(:post).permit(:title, :text)
end
end
Your index method has the Post class written in plural. Change it to Post.all
Modify your index action as:
def index
#posts = Post.all
end
Here Post is the model from where you are get all posts.

NoMethodError in Posts#index, undefined method `each' for nil:NilClass

I'm new to rails and following http://guides.rubyonrails.org/getting_started.html. I'm currently on section 5.8 which should list all the posts in my blog at localhost:3000/posts, but am instead getting a message:
NoMethodError in Posts#index
Showing /Users/sw/Code/blog/app/views/posts/index.html.erb where line #9 raised:
undefined method `each' for nil:NilClass
Extracted source (around line #9):
<% #posts.each do |post| %>
<tr>
<td><%= post.title %></td>
<td><%= post.text %></td>
Here's my posts_controller.rb:
class PostsController < ApplicationController
def index
#post = Post.all
end
def new
end
def create
#post = Post.new(params[:post].permit(:title, :text))
#post.save
redirect_to #post
end
def show
#post = Post.find(params[:id])
end
private
def post_params
params.require(:post).permit(:title, :text)
end
end
And here's my index.html.erb:
<table>
<tr>
<th>Title</th>
<th>Text</th>
</tr>
<% #posts.each do |post| %>
<tr>
<td><%= post.title %></td>
<td><%= post.text %></td>
</tr>
<% end %>
I've been searching all over and haven't been able to find an answer!
You are looping through a variable #posts, but in your index you are assigning a variable #post.
Thus, in your posts_controller.rb replace
def index
#post = Post.all
end
with
def index
#posts = Post.all
end

Resources