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
Related
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 %>
I am currently trying to create a search method. I have a database all setup; however, I am running into the errors:
ActiveRecord::RecordNotFound in ArticlesController#index
and:
Couldn't find Article with 'id'=all
Here is the pertinent code:
Articles_controller.rb
class ArticlesController < ApplicationController
def index
#articles = Article.all
#articles = Article.search(params[:id])
end
def show
#article = Article.find(params[:search])
end
def new
#article = Article.new
end
def edit
#article = Article.find(params[:id])
end
def create
#article = Article.new(params.require(:article).permit(:title, :text))
if #article.save
redirect_to #article
else
render 'new'
end
end
def update
#article = Article.find(params[:id])
if #article.update(article_params)
redirect_to #article
else
render 'edit'
end
end
def destroy
#article = Article.find(params[:id])
#article.destroy
redirect_to articles_path
end
private
def article_params
params.require(:article).permit(:title, :text)
end
end
article.rb
class Article < ActiveRecord::Base
validates :title, presence: true,
length: { minimum: 5 }
def self.search(search)
if search
#article = Article.find(:all, :conditions => ['name LIKE ?', "%#{search}%"])
else
#article = Article.find(:all)
end
end
end
index.rb
<h1>Listing articles</h1>
<%= link_to 'New article', new_article_path %>
<table>
<tr>
<th>Title</th>
<th>Text</th>
<th colspan="3"></th>
</tr>
<% #articles.each do |article| %>
<tr>
<td><%= article.title %></td>
<td><%= article.text %></td>
<td><%= link_to 'Show', article_path(article) %></td>
<td><%= link_to 'Edit', edit_article_path(article) %></td>
<td><%= link_to 'Destroy', article_path(article),
method: :delete,
data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
<%= form_tag articles_path, :method => 'get' do %>
<p>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "Search", :name => nil %>
</p>
<% end %>
</table>
Sorry for all the code to look through. The errors I am getting are from running localhost:3000/articles, where I receive these error messages from the server. I should note that I am still very new to both Ruby and Ruby on Rails; however, I aim to learn and find seeing proper code helps me quite significantly (I am dyslexic and tend to be a visual learner).
I truly appreciate your help, thanks in advance.
I think find can not take :all. the documentation says
"Using the find method, you can retrieve the object corresponding to the specified primary key that matches any supplied options. I think this is enough
Article.where('name LIKE ?', "%#{search}%")
or if you find all the articles
Article.all
Why do you have #articles = Article.search(params[:id]) in the index method?
Also, the stack trace will tell you exactly on which line the error occurs
Trying out ruby, i just asked a question but here's another, getting undefined method `each' for # and i tried a lot of stuff
<h1>This is the index page</h1>
<p>I need to get the new action running!</p>
<%= link_to 'My Blog', controller: 'posts' %>
</br>
<%= link_to 'New post', new_post_path %>
<h1>Listing posts</h1>
<table>
<tr>
<th>Title</th>
<th>Text</th>
</tr>
<% #posts.each do |post| %> ///<----ERROR HERE!
<tr>
<td><%= posts.title %></td>
<td><%= posts.description %></td>
<td><%= link_to 'Show', posts_path(posts) %></td>
<td><%= link_to 'Edit', edit_posts_path(posts) %></td>
</tr>
<% end %>
</table>
This is my controller:
class PostsController < ApplicationController
def index
#posts = Post.new
end
def edit
#posts = Post.find(params[:id])
end
def update
#posts = Post.find(params[:id])
if #posts.update(posts_params)
redirect_to #posts
else
render 'edit'
end
end
def new
#posts = Post.new
end
def create
#posts = Post.new(posts_params)
if #posts.save
redirect_to #post
else
render 'new'
end
end
def show
#posts = Post.find(params[:id])
end
private
def posts_params
params.require(:posts).permit(:title, :description)
end
end
I'm pretty sure i changed eveything to be matching like #posts from #post, i would appreciate if someone could help me again, i've tried looking for an answer but not getting luck, thank you
In your controller under the index do:
def index
#posts = Post.all
end
Then in your view after your each do refer to the variable as post, not posts.
<% #posts.each do |post| %>
<tr>
<td><%= post.title %></td>
<td><%= post.description %></td>
<td><%= link_to 'Show', post_path(post) %></td>
<td><%= link_to 'Edit', edit_post_path(post) %></td>
</tr>
<% end %>
Modify the index method in your controller to the following:
def index
#posts = Post.all
end
Post.new returns a single (empty) objet, the each method expects an enumerable (array, hash, collection,...), hence the error.
Your #posts instance variable is pointing to a new post record instead of a collection of posts. You need an array to iterate over instead of a single post.
If you want to call .each on an object, that object has to be made up of a collection of data (even if the "collection" has one element).
You're calling Post.new - meaning the .each method is going to return an exception that it cannot cycle through the expected collection.
You need to do the following:
#app/controllers/posts_controller.rb
class PostsController < ApplicationController
def index
#posts = Post.all
end
end
This should get your code working.
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.
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