undefined method `each' for nil:NilClass - help needed - ruby-on-rails

I am teaching myself Ruby on Rails and trying to build a blog through a tutorial. I saw some of these answers, and it seems as though my syntax is right, but I'm getting the error in the title.
Here is my articles_controller code:
class ArticlesController < ApplicationController
before_action :set_article, only: [:edit, :update, :show, :destroy]
def index
#articles = Article.paginate(page: params[:page], per_page: 5)
end
def new
#article = Article.new
end
def edit
end
def create
#article = Article.new(article_params)
#article.user = User.first
if #article.save
flash[:success] = "Article was successfully created"
redirect_to article_path(#article)
else
render 'new'
end
end
def update
if #article.update(article_params)
flash[:success] = "Article was updated"
redirect_to article_path(#article)
else
flash[:danger] = "Article was not updated"
render 'edit'
end
end
def show
end
def destroy
#article.destroy
flash[:danger] = "Article was deleted"
redirect_to articles_path
end
private
def set_article
#article = Article.find(params[:id])
end
def article_params
params.require(:article).permit(:title, :description)
end
end
And here is my index.html.erb:
<h1 align="center">Listing all articles</h1>
<% #articles.each do |article| %>
<div class="row">
<div class="col-xs-8 col-xs-offset-2">
<div class="well well-lg">
<div class="article-title">
<%= link_to article.title, article_path(article) %>
</div>
<div class="article-body">
<%= truncate(article.description, length: 100) %>
</div>
<div class="article-meta-details">
<small>Created by: <%= article.user.username if article.user %>, <%= time_ago_in_words(article.created_at) %> ago, last updated: <%= time_ago_in_words(article.updated_at) %> ago</small>
</div>
<div class="article-actions">
<%= link_to "Edit", edit_article_path(article), class: "btn btn-xs btn-primary" %>
<%= link_to "Delete", article_path(article), method: :delete, data: { confirm: "Are you sure you want to delete this article?"}, class: "btn btn-xs btn-danger" %>
</div>
</div>
</div>
</div>
<% end %>
I would appreciate any help I can get. Thanks.

I think your syntax in the index method is wrong.
#articles = Article.paginate(page: params[:page], per_page: 5)
Should be
#articles = Article.all.paginate(page: params[:page], per_page: 5)

Related

using ajax for acts_as_votable to avoid page reload

I'm using acts_as_voteable for upvote/downvote on a tweets page which works fine. however it reloads the page when i do this which i want to avoid
<% #tweets.each do |tweet| %>
<div class="card">
<div class="card-description">
<h4><%= link_to tweet.user.username, user_path(tweet.user) %></h4>
<p class="tweet-content"><%= tweet.content %></p>
<p><%= tweet.created_at.strftime("%B %d %Y, %l:%M%P") %></p>
<%= link_to like_tweet_path(tweet), method: :put do %>
<p>Upvote <%= tweet.get_upvotes.size %>
<% end %>
<%= link_to dislike_tweet_path(tweet), method: :put do %>
Downvote <%= tweet.get_downvotes.size %></p>
<% end %>
</div>
</div>
<% end %>
class TweetsController < ApplicationController
before_action :authenticate_user!, :except => [:index]
def index
# #tweets = Tweet.all.order("created_at DESC")
#tweets = Tweet.paginate(page: params[:page], per_page: 7).order('created_at DESC')
#tweet = Tweet.new
#user = current_user
end
def show
#tweet = Tweet.find(params[:id])
end
def new
# #tweet = Tweet.new
end
def create
# #user = current_user
#user = User.find(params[:user_id])
#tweet = Tweet.new(tweet_params)
#tweet.user = #user
if #tweet.save
redirect_to user_tweets_path
end
end
def edit
#tweet = Tweet.find(params[:id])
end
def update
#tweet = Tweet.find(params[:id])
#tweet.update(tweet_params)
redirect_to tweets_path
end
def upvote
#tweet = Tweet.find(params[:id])
#tweet.upvote_by current_user
# redirect_to :tweets
if request.xhr?
head :ok
else
redirect_to tweets_path
end
end
def downvote
#tweet = Tweet.find(params[:id])
#tweet.downvote_by current_user
redirect_to :tweets
end
private
def tweet_params
params.require(:tweet).permit(:content)
end
end
You can use remote: true in the link_to tag.
For example:
You have <%= link_to like_tweet_path(tweet), method: :put do %>
You can have it this way <%= link_to like_tweet_path(tweet), method: :put, remote: true do %>
Then just handle the request with format.js

Rails app - extra record displaying

I have an app that allows users to add albums they like to a database. Anyone can then come along and write a review for that album. Pretty simple.
I am running into a problem where an extra record appears to be created for the reviews on each album's show page. Every album, even if it has not ever been reviewed, has an additional, seemingly empty review being displayed when I use .each to display each review in the album show page. I want to get rid of that.
Here is an image of the problem. I have used CSS to highlight reviews in red. As you can see, there is an empty review at the bottom. When I inspect the review in question, it's raty title is "Not reviewed yet!"
Here is my albums_controller:
class AlbumsController < ApplicationController
before_action :set_album, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!, only: [:edit, :new, :update, :destroy]
def index
#albums = Album.all
if params[:search].nil?
#albums = Album.all.order(year: :desc).order(title: :asc).paginate(:page => params[:page], :per_page => 24)
else
#albums = #albums.where("albums.title || albums.year || albums.artist LIKE ?", "%#{params[:search]}%").order(year: :desc).order(title: :asc).paginate(:page => params[:page], :per_page => 24)
end
end
def show
if #album.reviews.blank?
#average_review = 0
else
#average_review = #album.reviews.average(:rating).round(2)
end
#review = #album.reviews.build
end
def new
#album = Album.new
end
def edit
end
def create
#album = current_user.albums.build(album_params)
respond_to do |format|
if #album.save
format.html { redirect_to #album, notice: 'Album was successfully created.' }
format.json { render :show, status: :created, location: #album }
else
format.html { render :new }
format.json { render json: #album.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #album.update(album_params)
format.html { redirect_to #album, notice: 'Album was successfully updated.' }
format.json { render :show, status: :ok, location: #album }
else
format.html { render :edit }
format.json { render json: #album.errors, status: :unprocessable_entity }
end
end
end
def destroy
#album.destroy
respond_to do |format|
format.html { redirect_to albums_url, notice: 'Album was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_album
#album = Album.find(params[:id])
end
def album_params
params.require(:album).permit(:title, :artist, :year, :cover)
end
end
Here is the album show page, which is where the extra review is being displayed:
<div class="row">
<div class="col-xs-10 col-md-6 col-md-push-3 col-xs-push-1 top bottom">
<%= image_tag #album.cover, class: 'show_image' %>
<h2><%= #album.title %></h2>
<h4><%= #album.artist %></h4>
<h5><%= #album.year %></h5>
<p class="white">Average Review<div class="average-review-rating" data-score=<%= #average_review %>></div></p>
<% if user_signed_in? %>
<% if #album.user_id == current_user.id %>
<%= link_to 'Edit', edit_album_path(#album), class: 'grey' %>
| <%= link_to 'Delete', album_path, method: :delete, data: {confirm: "Are you sure?"}, class: 'grey' %>
<% end %>
<% end %>
<br /><br />
<h4>Reviews</h4>
<% if user_signed_in? %>
<p class="grey">Write a review</p>
<%= form_for [#album, #review] do |r| %>
<div class="form-group">
<div id="rating-form">
<label>Rating</label>
</div>
</div>
<div class="form-group">
<%= r.text_area :comment, class: 'form-control', placeholder: "Write a comment" %>
</div>
<div class="form-group">
<%= r.submit "Create", class: 'btn btn-success' %>
</div>
<% end %>
<% end %>
<br />
<% #album.reviews.each do |r| %>
<div class="red">
<div class="review-rating" data-number="<%= r.rating %>">
</div>
<p class="white"><%= r.comment %></p>
<% if user_signed_in? %>
<% if current_user.id == r.user_id %>
<%= link_to 'Edit', edit_album_review_path(#album, r.id), class: 'grey' %> |
<%= link_to 'Delete', album_review_path(#album, r.id), method: :delete, data: {confirm: "Are you sure?"}, class: 'grey' %>
<% end %>
<% end %>
<br /><br />
</div>
<% end %>
</div>
</div>
<script>
$('.review-rating').raty({
readOnly: true,
score: function() {
return $(this).attr('data-number');
},
path: '/assets/'
});
$('#rating-form').raty({
path: '/assets/',
scoreName: 'review[rating]'
});
$('.average-review-rating').raty({
readOnly: true,
path: '/assets/',
score: function() {
return $(this).attr('data-score')
}
});
</script>
Any help would be very appreciated!
The problem here is on the last line of your show method: #review = #album.reviews.build. This line not only creates a new Review instance and assigns it to #review, but it also adds that instance to the array in #album.reviews. So, in your view, when you iterate over #album.reviews, you will see all of the persisted reviews as well as the one new, not persisted review that was built with build.
The easiest way to fix this would be to add this line in your view:
<% #album.reviews.each do |r| %>
<% next unless r.persisted? %>
Another solution would be to associate the new review with the album, but not on the #album instance. In the controller:
#review = Review.new(album: #album)
I think it could be because of last line in show.
#review = #album.reviews.build
It builds an empty review.

Users can't visit other users in my ruby application

I looked around a lot and found only one question like the one I am asking, And the information in it did not help me with my issues. What I am having an issue with is my users, I have several users. You're able to navigate to the page that displays every user, each one is clickable. But when ever I'm signed in to a user say Profile(1) and I wanna visit Profile(2) page it just loads Profile(1)'s credentials. Age, Bio, and Picture. Whats my issues here? It may be a simple fix and if so then thank you for the help in advance!
This is the page that list all users index.html.erb,
<div class="all_users">
<div class="container">
<p id="notice"><%= notice %></p>
<h1>Listing Users</h1>
<table>
<thead>
<tr>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% #users.each do |user| %>
<ul class="media-list">
<li class="media">
<div class="media-left">
<%= link_to image_tag user.profile_picture.url(:thumb) %>
</a>
</div>
<div class="media-body">
<h4 class="media-heading">Name: <%= link_to user.first_name, dashboard_path %></h4>
<p>Age: <%= user.age %></p>
<p><%= user.bio %></p>
</div>
</li>
</ul>
<tr>
<td><%= link_to 'Show', user %></td>
<td><%= link_to 'Edit', edit_user_path(user) %></td>
<td><%= link_to 'Destroy', #user, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
<br/>
<%= link_to 'New User', new_user_path %>
<%= link_to 'Login', login_path %>
</div>
</div>
Here is the profile page for the users show.html.erb,
<div class="show">
<div class="col-md-3">
<div class="thumbnail">
<% else %>
<%= image_tag #user.profile_picture.url(:medium) %>
<div class="caption">
<h2><%= #user.name %></h2>
<p>Message This User <i class="fa fa-envelope-o fa-lg"> </i></p>
<p>Report This User <i class="fa fa-exclamation fa-lg"> </i></p>
<p>Block this User <i class="fa fa-user-times fa-lg"> </i></p> <p>Add As Friend Follow</p>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">Bio for <%= #user.first_name %></div>
<p class="bio">
<%= #user.bio %>
</p>
</div>
</div>
<div class="col-md-4">
<div class="panel panel-default">
<%= form_for :post, url: posts_path do |f| %>
<div class="panel-heading">
<i class="fa fa-pencil-square"></i> <%= f.label :Status %> |<br>
</div>
<div class="panel-body">
<%= f.text_area :body, placeholder: "What's new?" %>
</div>
<p>
<%= f.submit %>
</p>
<% end %>
</div>
<%- #posts.each do |post| %>
<div class="panel panel-default">
<div class="panel-heading-gray"> <%= image_tag #user.profile_picture.url(:thumb) %> <h5 class="user-name"><%= #user.name %></h5> <h6 class="time-posted"><%= post.created_at.strftime("%B, %d, %Y") %></h6></div>
<div class="panel-body"><%= link_to post.body, post %></div>
<div class="panel-footer">
<%= render post.comments %>
<p class="Like-option">Like ·</p>
<p class="comment-form">Comment</p>
<p class="view-option">· View</p>
<p class="comment-profile-picture">
<%= image_tag #user.profile_picture.url(:thumb) %>
</p>
<%= #post.comments.count %>
<div id="comments-form">
<%= render "comments/form", :post => post %>
</div>
</div>
</div>
<% end %>
</div>
Here is my users_controller.rb,
class UsersController < ApplicationController
before_action :set_user, only: [:show, :edit, :update, :destroy]
after_action :signed_in_after_register, only: :create
def index
#users = User.all
#user = User.find(session[:user_id])
end
def dashboard
#user = User.find(session[:user_id]) unless session[:user_id] == ""
redirect_to login_path, notice: "You're not logged in" unless #user
#posts = #user.posts.order("created_at DESC").limit(3)
#comment = Comment.new
#post = Post.new
end
def newsfeed
#user = User.find(session[:user_id]) unless session[:user_id] == nil
redirect_to login_path, notice: "You're not logged in" unless #user
#posts = #user.posts.order("created_at DESC").limit(3)
end
def nav
#user = User.find(session[:user_id])
end
def posts
#user = User.find(session[:user_id])
#posts = #user.posts
end
def destroy
#user = User.find(session[:user_id]) unless session[:user_id] == ""
redirect_to login_path, notice: "You're not logged in" unless #user
end
def welcome
#user = User.find(session[:user_id]) unless session[:user_id] == ""
redirect_to login_path, notice: "You're not logged in" unless #user
end
def show
#user = User.find(params[:user_id]) unless session[:user_id] == ""
redirect_to login_path, notice: "You're not logged in" unless #user
#posts = #user.posts.order("created_at DESC").limit(3)
#comment = Comment.new
#post = Post.new
end
def new
#post = Post.new(params[:post_id])
#user = User.new
end
def edit
end
def create
#user = User.new(user_params)
respond_to do |format|
if #user.save
format.html { redirect_to dashboard_path, notice: 'User was successfully created!' }
format.json { render :show, status: :created, location: #user }
else
format.html { render :new }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #user.update(user_params)
format.html { redirect_to dashboard_path, notice: 'User was successfully updated.' }
format.json { render :show, status: :ok, location: #user }
else
format.html { render :edit }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
def destroy
#user.destroy
respond_to do |format|
format.html { redirect_to users_url, notice: 'User was successfully destroyed.' }
format.json { head :no_content }
end
end
private
def set_user
#user = User.find(params[:id])
end
def signed_in_after_register
session[:user_id] = #user.id
end
def user_params
params.require(:user).permit(:first_name, :last_name, :bio, :password, :password_confirmation, :email, :age, :profile_picture, :post, :body)
end
end
and this is my user model user.rb,
class User < ActiveRecord::Base
has_secure_password
validates :first_name, :last_name, :email, presence: true, uniqueness: true
validates_inclusion_of :age, in: 10..100
validates :password, presence: true
has_many :posts
has_attached_file :profile_picture, :styles => { :medium => "300x300>", :thumb => "100x100>" },
:default_url => "app/assets/images/missing.png",
:path => ":rails_root/public/system/:class/:attachment/:id_partition/:style/:filename"
validates_attachment_content_type :profile_picture, :content_type => /\Aimage\/.*\Z/
I tried putting in User.find(params[:user_id]) and I get the following error
ActiveRecord::RecordNotFound in UsersController#show
Couldn't find User with 'id'=
EDIT: Here is my routes file,
Rails.application.routes.draw do
root 'welcome#welcome'
get 'login' => 'sessions#login', :as => :login
get 'dashboard' => 'users#dashboard', :as => :dashboard
post 'logging/user' => 'sessions#create'
get 'logout' => 'sessions#destroy', :as => :logout
get 'about' => 'about'
get 'newsfeed' => 'users#newsfeed'
resources :users, except: :show
get 'profile/:id' => 'users#show', as: :profile
resources :posts do
resources :comments
end
get 'index' => 'posts#index'
get 'register' => 'users#new', :as => :register
end
Which link are you clicking to view a user's profile?
<h4 class="media-heading">Name: <%= link_to user.first_name, dashboard_path %></h4>
or:
<td><%= link_to 'Show', user %></td>
If it's the first one why are you linking to dashboard_path? Seems like that should be linking to user_path(user) right?
Might also help to show us your routes file.

NoMethodError in MembersController#index undefined method `total_pages' for #<Micropost::ActiveRecord_Associations_CollectionProxy:0x007ffc26104288>

The error output is:
NoMethodError in MembersController#index
undefined method `total_pages' for #<Micropost::ActiveRecord_Associations_CollectionProxy:0x007ffc26104288>
Application trace is:
app/views/shared/_feed.html.erb:5:in `_app_views_shared__feed_html_erb__933429040368905157_70360748756160'
app/views/members/index.html.erb:4:in `_app_views_members_index_html_erb__2919315027143638402_70360970104820'
Update:
Source near error:
arel.public_send(method, *args, &block)
else
super # marked red
end
end
end
Additional info:
app/views/members/index.html.erb renders two partials using another controller, microposts_controller. So I'll show contents of both controllers and of the two partials.
# app/views/members/index.html.erb
<%= render 'shared/micropost_form', :locals => { :micropost => #micropost } %>
<%= render 'shared/feed', :locals => { :feed_items => #feed_items } %>
MembersController
class MembersController < ApplicationController
def index
#micropost = current_user.microposts.build
#feed_items = current_user.microposts
end
end
micropost_controller.rb
# controllers/micropost_controller.rb
class MicropostsController < ApplicationController
before_action :logged_in_user, only: [:create, :destroy]
before_action :correct_user, only: :destroy
def create
#micropost = current_user.microposts.build(micropost_params)
if #micropost.save
flash[:success] = "Micropost created!"
redirect_to '/members'
else
#feed_items = []
render '/members'
end
end
def destroy
#micropost.destroy
flash[:success] = "Micropost deleted"
redirect_to request.referrer || '/members'
end
private
def micropost_params
params.require(:micropost).permit(:content, :picture)
end
def correct_user
#micropost = current_user.microposts.find_by(id: params[:id])
redirect_to '/members' if #micropost.nil?
end
end
_micropost_form.html.erb
# shared/_micropost_form.html.erb
<%= form_for(#micropost, html: { multipart: true }) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="field">
<%= f.text_area :content, placeholder: "Compose new micropost (420 chars max)..." %>
</div>
<%= f.submit "Post", class: "btn btn-primary" %>
<span class="picture">
<%= f.file_field :picture, accept: 'image/jpeg,image/gif,image/png' %>
</span>
<% end %>
<script type="text/javascript">
$('#micropost_picture').bind('change', function() {
size_in_megabytes = this.files[0].size/1024/1024;
if (size_in_megabytes > 5) {
alert('Maximum file size is 5MB. Please choose a smaller file.');
}
});
</script>
_feed.html.erb
# shared/_feed.html.erb
<% if #feed_items.any? %>
<ol class="microposts">
<%= render #feed_items %>
</ol>
<%= will_paginate #feed_items %>
<% end %>
You want to paginate your records using will_paginate in view, but you didn't paginate them in your controller:
def index
#micropost = current_user.microposts.build
#feed_items = current_user.feed.paginate(page: params[:page])
end

undefined method `picture' for nil:NilClass using carrierwave

I am making a form in my rails application where people have the option of adding images and I am using 'carrierwave' but I am getting an undefined method error on the edit page. Here is the code for the form:
<%= title "Add Item to #{#todo_list.title}" %>
<%= form_for [#todo_list, #todo_item], builder: FoundationFormBuilder do |form| %>
<%= render partial: 'form', locals: { form: form } %>
<%= form.file_field :picture %>
<% end %>
Here I can see the upload button and it is working fine but on the edit page I get the above stated error. Code for my edit page:
<%= title "Editing Todo Item" %>
<%= form_for [#todo_list, #todo_item], builder: FoundationFormBuilder do |form| %>
<%= render partial: 'form', locals: { form: form } %>
<% end %>
<div class="row">
<div class="small-12 columns">
<%= link_to "Delete", todo_list_todo_item_path(#todo_list, #todo_item), method: :delete, data: { confirm: "Are you sure?" }, class: "button radius expand alert" %>
</div>
<%= #todo_item.picture %>
</div>
Why is this showing an undefined method error. I tried creating a method in my todo_item model but its still showing the above error.
Controller for todo_item:
class TodoItemsController < ApplicationController
before_action :require_user
before_action :find_todo_list
before_action :set_back_link, except: [:index]
def index
go_back_link_to todo_lists_path
end
def new
#todo_item = #todo_list.todo_items.new
end
def create
#todo_item = #todo_list.todo_items.new(todo_item_params)
if #todo_item.save
flash[:success] = "Added todo list item."
redirect_to todo_list_todo_items_path
else
flash[:error] = "There was a problem adding that todo list item."
render action: :new
end
end
def edit
#todo_item = #todo_list.todo_items.find(params[:id])
end
def update
#todo_item = #todo_list.todo_items.find(params[:id])
if #todo_item.update_attributes(todo_item_params)
flash[:success] = "Saved todo list item."
redirect_to todo_list_todo_items_path
else
flash[:error] = "That todo item could not be saved."
render action: :edit
end
end
def destroy
#todo_item = #todo_list.todo_items.find(params[:id])
if #todo_item.destroy
flash[:success] = "Todo list item was deleted."
else
flash[:error] = "Todo list item could not be deleted."
end
redirect_to todo_list_todo_items_path
end
def complete
#todo_item = #todo_list.todo_items.find(params[:id])
#todo_item.toggle_completion!
redirect_to todo_list_todo_items_path, notice: "Todo item updated."
end
def url_options
{ todo_list_id: params[:todo_list_id] }.merge(super)
end
private
def set_back_link
go_back_link_to todo_list_todo_items_path(#todo_list)
end
def find_todo_list
#todo_list = current_user.todo_lists.find(params[:todo_list_id])
end
def todo_item_params
params[:todo_item].permit(:content)
end
end
To display your image you should change
<%= #todo_item.picture %>
to
<%= image_tag(#todo_item.picture_url) %>

Resources