What is causing NoMethodError in my CRUD? - ruby-on-rails

I am student working on my first project on my own. The user is supposed to be able to create a to-do list. I have my form partial displayed and am trying to now render the list items through a partial. After altering my routes.rb and items_controller.rb I still receive NoMethodError.
Here is the stack trace.
Completed 500 Internal Server Error in 23ms (ActiveRecord: 0.2ms)
ActionView::Template::Error (undefined local variable or method `items' for #<#<Class:0x007fa1c3b4e238>:0x007fa1bd6f2258>):
1: <% items.each do |i| %>
2: <%= i.name %>
3: <% end %>
app/views/items/_item.html.erb:1:in `_app_views_items__item_html_erb___4201771908086516106_70166314068980'
app/views/users/show.html.erb:5:in `_app_views_users_show_html_erb__1693372631105662933_70166313045680'
items_controller.rb
class ItemsController < ApplicationController
def index
#items = Item.all
end
def show
#item = Item.find(params[:id])
end
def new
#item = Item.new
end
def edit
#item = Item.find(params[:id])
end
def create
#item = Item.new(params.require(:item).permit(:name))
if #item.save
flash[:notice] = "The item was added to your list."
redirect_to :show
else
flash[:error] = "There was a problem creating your item."
redirect_to :new
end
end
end
routes.rb
Rails.application.routes.draw do
get 'welcome/index'
get 'welcome/about'
# resources :welcome, only: [] do
# collection do
# get 'about'
# get 'index'
# end
# end
devise_for :users
resources :users, only: [:show]
resources :items
root to: 'welcome#index'
end
users/show.html.erb
<h1>Welcome <%= current_user.name %></h1>
<p>Add an item</p>
<%= render partial: 'items/form', locals: { item: #new_item } %>
<%= render partial: 'items/item', locals: { item: #items } %>
items/_item.html.erb
<% items.each do |i| %>
<%= i.name %>
<% end %>
EDIT: Here is my users_controller.rb
class UsersController < ApplicationController
before_action :authenticate_user!
def show
#user = User.find(params[:id])
#new_item = Item.new
end
end

You need to use local variable item, which you passed to the partial _item.html.erb. :
<% item.each do |i| %>
<%= i.name %>
<% end %>
and ...
class UsersController < ApplicationController
before_action :authenticate_user!
def show
#user = User.find(params[:id])
#new_item = Item.new
#items = Item.all
end
end

Related

In Rails, show for nested resources not working

I am using nested resources. When I click on a goal that's been created, I keep getting this error:
param is missing or the value is empty: goal
And it directs me to the "params.require..." line:
private
def goal_params
params.require(:goal).permit(:text)
end
I'm not sure what's causing this. I can create and show the list. But when I click on a goal I get this error. I'm new to rails and I'm at my wit's end.
My view:
<h1>Listing goals</h1>
<table>
<tr>
<th>Text</th>
<th></th>
</tr>
<% #user.goals.each do |goal| %>
<tr>
<td><%= link_to goal.text, user_goals_path(#user, #goal)%></td>
</tr>
<% end %>
</table>
<h2>Add a comment:</h2>
<%= form_for([#user, #user.goals.build]) do |form| %>
<p>
<%= form.text_area :text %>
</p>
<p>
<%= form.submit %>
</p>
<% end %>
My controller:
class GoalsController < ApplicationController
def index
#user = User.find(params[:user_id])
#goal = #user.goals.find(goal_params)
end
def show
#user = User.find(params[:user_id])
#goal = #user.goals.find(:id)
#also tried goal_params and :goal_id instead of :id
end
def new
#user = User.find(params[:user_id])
#goal = #user.goals.new
end
def create
#user = User.find(params[:user_id])
#goal = #user.goals.build(goal_params)
#goal.user = current_user
if #goal.save
redirect_to new_user_goal_path, notice: "Success!~"
else
redirect_to new_user_goal_path, alert: "Failure!"
end
#to root_path
end
private
def goal_params
params.require(:goal).permit(:text)
end
end
My routes:
Rails.application.routes.draw do
devise_for :users
resources :user do
resources :goals
end
devise_scope :user do
authenticated :user do
root 'home#index', as: :authenticated_root
end
unauthenticated do
root 'devise/sessions#new', as: :unauthenticated_root
end
end
end
My show.html.erb:
<p>
<strong>Text:</strong>
<%= #goal.text %>
</p>
First thing, in the show
#goal = #user.goals.find(:id)
Should be
#goal = #user.goals.find(params[:id])
You said you tried with #user.goals.find(goal_params) in show action and I see it in your index action also. This will call the goal_params method, which require params[:goal] while your index or show request does not send to server, only when you submit the form, you will have that params. This is the cause of your error.
Second thing, your index should use
#goals = #user.goals
INSTEAD OF
#goal = #user.goals.find(goal_params)
Also, the strong parameters is used for create and update actions only to avoid mass assignment to our database. It's not used to find a record.

Clicking on a Username of another user links to my profile instead of the user's profile

I need help with this my code,that displays list of posts of users along with their username.What i want is, when i click on a username of a particular post, it should send me to that user's profile. instead, it send's to my own profile or the current user's profile whiles i want it to link me to the username i have clicked profile. (e.g like when you click on a username on Instagram, it links you to the user's profile so you can follow or unfollow and see their post)
Please i need help. what i'm i not doing right in my code.
i'm on rails 5.2.3 & ruby 2.3.3
Home
<div class="posts">
<% #posts.each do |post| %>
<section class="post">
<div class="user">
<div class="avatar">
<img src="assets/avater.jpg">
</div>
<%= link_to post.user.username, user_path(post.user), class: 'username' %>
</div>
<%= image_tag post.image, class: 'main-image' %>
<div class="description">
<% post.description.to_s.split(' ').each do |word| %>
<% if word.start_with?('#') %>
<%= link_to word, search_index_path(query: word) %>
<% else %>
<%= word %>
<% end %>
<% end %>
</div>
</section>
<% end %>
<%= paginate #posts %>
</div>
routes
Rails.application.routes.draw do
get 'search/index'
devise_for :users
get 'home/index'
resources :posts
root 'home#index'
resources :users, only: [:show, :edit, :update]
resources :posts, only: [:new, :create, :show, :destroy]
end
users controller
class UsersController < ApplicationController
before_action :find_user
def show
#user = User.find(params[:id])
#posts = current_user.posts.order(created_at: :desc)
end
def edit
end
def update
current_user.update(user_params)
redirect_to current_user
end
private
def find_user
#user = User.find(params[:id])
end
def user_params
params.require(:user).permit(:username, :name, :website,:bio, :email, :phone, :gender, :avatar)
end
end
post controller
class PostsController < ApplicationController
def new
#post = current_user.posts.build
end
def create
#post = Post.create(post_params)
redirect_to root_path
end
def show
#post = Post.find(params[:id])
end
def destroy
#post = current_user.posts.find(params[:id])
#post.destroy
redirect_to user_path(current_user)
end
private
def post_params
params.require(:post).permit(:description, :image, :user_id)
end
end
home controller
class HomeController < ApplicationController
before_action :authenticate_user!
def index
#posts = Post.order(created_at: :desc).page(params[:page]).per(5)
end
end
I guess the problem is that on the show method from users_controller, you are getting the posts from current_user instead of the user, it should be #posts = #user.posts.order(created_at: :desc)

how to access child new form from parent index page in rails?

I am trying to fetch booking controller's new form, from the cab index page. how can i fetch it? how can access the new form from cab index page where i have shown all the cabs which are added..
cab controller
class CabsController < ApplicationController
before_action :find_cab, only: [:show, :edit, :update, :destroy]
def index
#cabs = Cab.all.order("created_at DESC")
end
def new
#cab = Cab.new
end
def show
#reviews = Review.where(cab_id: #cab.id).order("created_at DESC")
if #reviews.blank?
#avg_review=0
else
#avg_review=#reviews.average(:rating).round(2)
end
end
def edit
end
def create
#cab = Cab.new(cab_params)
if #cab.save
redirect_to #cab
else
render 'new'
end
end
def update
if #cab.update(cab_params)
redirect_to #cab
else
render 'edit'
end
end
def destroy
#cab.destroy
redirect_to root_path
end
private
def find_cab
#cab = Cab.find(params[:id])
end
def cab_params
params.require(:cab).permit(:name, :number_plate, :seat, :image)
end
end
booking controller
class BookingsController < ApplicationController
before_action :find_booking, only: [:show, :edit, :update, :destroy]
before_action :find_cab
def index
#bookings = Booking.where(cab_id: #cab.id).order("created_at DESC")
end
def new
#booking = Booking.new
end
def show
end
def edit
end
def create
#booking = Booking.new(booking_params)
#booking.user_id = current_user.id
#booking.cab_id = #cab.id
if #booking.save
redirect_to cab_booking_path(#cab, #booking)
else
render 'new'
end
end
def update
end
def destroy
end
private
def find_booking
#booking = Booking.find(params[:id])
end
def find_cab
#cab = Cab.find(params[:cab_id])
end
def booking_params
params.require(:booking).permit(:date, :address, :start_destination, :destination, :start_date, :end_date, :contact_no)
end
end
routes
resources :cabs do
resources :bookings
end
cab/index.html.erb
<div class="container">
<h2>All Cabs</h2>
<div class="row">
<% #cabs.each do |cab| %>
<div class="col-sm-6 col-md-3">
<div class="thumbnail">
<%= link_to image_tag(cab.image.url(:medium), class: 'image'), cab %><br>
Cab Name : <h4><%= cab.name %></h4>
<%= link_to "Book Now", new_cab_booking_path(#cab, #booking) %> # i wanted to create this link
</div>
</div>
<% end %>
</div>
<%= link_to "Add Cab", new_cab_path, class: 'btn btn-default' %>
the error i am getting is
No route matches {:action=>"new", :cab_id=>nil, :controller=>"bookings"} missing required keys: [:cab_id]
No route matches {:action=>"new", :cab_id=>nil,
:controller=>"bookings"} missing required keys: [:cab_id]
The problem is with this line
<%= link_to "Book Now", new_cab_booking_path(#cab, #booking) %>
which should be
<%= link_to "Book Now", new_cab_booking_path(cab) %>

NameError in Users#show - Rails

I am following Michael Hurtl's Rails Tutorial and In Chapter 11 When i want to view the profile page of the User i get this error :
NameError in Users#show undefined local variable or method `micropost' and This line of Code is highlighted in red :
<%= link_to micropost.user.name , micropost.user%>
Here's My code:
microposts_controller.rb
class MicropostsController < ApplicationController
before_action :authenticate_user! , only: [:create,:destroy]
def create
#micropost = current_user.microposts.build(micropost_params)
if #micropost.save
flash[:success] = "Micropost created"
redirect_to root_url
else
render 'pages/home'
end
end
def destroy
end
private
def micropost_params
params.require(:micropost).permit(:content)
end
end
users_controller.rb
class UsersController < ApplicationController
before_action :authenticate_user! , only: [:edit,:update,:destroy]
def index
#users = User.all
end
def show
#user = User.find(params[:id])
#microposts = #user.microposts
end
end
microposts/_microposts.html.erb
<%= link_to micropost.user.name , micropost.user%>
views/users/show.html.erb
<h2>User Profile</h2>
<% if #user.microposts.any? %>
<h3>Microposts</h3>
<%= #user.microposts.count%>
<%= render 'microposts/microposts' %>
<%end%>
it seems you didn't set micropost variable to partial
you can fix it in next way:
<%= render partial: 'microposts/_microposts', collection: #microposts %>
You should have something like this in your partial:
<% #microposts.each do |micropost| %>
<%= link_to micropost.user.name , micropost.user%>
<% end %>

Trying to add a partial form to my index page. How do I pass multiple variables to generate the form?

I have an index page of art that I vote on with ratings model. I can vote on the show page but I want it to be able to vote on the index page also. The form for the ratings has three variables. How should the Art Controller index page look and the code for the index html page. I'm getting an error that "rating" is undefined. Please help, this is like the last hurdle I got to get over to complete this project.
**Update: I changed my routes so the form only has two variables now. But still having trouble rendering the form on the index page.
Routes to a new rating
new_art_rating GET /arts/:art_id/ratings/new(.:format)
Routes.rb
resources :campaigns do
resources :lyrics do
member do
get "like", to: "lyrics#upvote"
get "dislike", to: "lyrics#downvote"
end
resources :comments
end
resources :arts do
member do
get "like", to: "arts#upvote"
get "dislike", to: "arts#downvote"
end
resources :commentarts
end
end
resources :arts do
resources :ratings
end
Art Index
<% #arts.each do |art| %>
<div class="container-md">
<%= render partial: 'ratings/form', :locals =>{:campaign => #campaign, :art => #art, :rating => #art.rating} %>
<%= link_to campaign_art_path(#campaign, art) do %>
<%= image_tag art.image.url(:small) %>
<% end %>
Arts Controller
class ArtsController < ApplicationController
before_action :tag_cloud, :only => [:index]
load_and_authorize_resource :only => [:show, :edit, :update, :destroy]
before_action :find_post, only: [:show, :edit, :update, :destroy, :upvote, :downvote]
before_action :set_campaign
before_action :authenticate_user!, except: [:index, :show]
impressionist :actions=>[:show,:index], :unique => [:impressionable_type, :impressionable_id, :session_hash]
def index
#arts = Art.all.order("created_at DESC").paginate(:page => params[:page], :per_page => 10)
#rating = Rating.new
end
def show
#commentarts = Commentart.where(art_id: #art)
#ratings = Rating.where(art_id: #art)
#random_art = Art.where.not(id: #art).order("RANDOM()").first
end
def new
#art = Art.new
end
def create
#art = Art.new(post_params)
#art.user_id = current_user.id
#art.campaign_id = #campaign.id
if #art.save
redirect_to([#art.campaign, #art])
else
render 'new'
end
end
def edit
end
def update
if #art.update(post_params)
redirect_to([#art.campaign, #art])
else
render 'edit'
end
end
def destroy
#art.destroy
redirect_to root_path
end
def upvote
#art.upvote_by current_user
redirect_to([#art.campaign, #art])
end
def downvote
#art.downvote_by current_user
redirect_to([#art.campaign, #art])
end
def tagged
if params[:tag].present?
#arts = Art.tagged_with(params[:tag]).order("created_at desc")
else
#arts = Art.all.order("created_at desc")
end
end
def tag_cloud
#tags = Art.tag_counts_on(:tags)
end
private
def find_post
#art = Art.find(params[:id])
end
def set_campaign
#campaign = Campaign.find(params[:campaign_id])
end
def post_params
params.require(:art).permit( :image, :description, :artist, :typeart, :link)
end
end
Ratings Controller
class RatingsController < ApplicationController
before_action :authenticate_user!
def create
#art = Art.find(params[:art_id])
#rating = Rating.create(params[:rating].permit(:rate))
#rating.user_id = current_user.id
#rating.art_id = #art.id
if #rating.save
redirect_to([#art.campaign, #art])
else
render 'new'
end
end
end
Form view
<%= simple_form_for([#art, #art.ratings.build]) do |f| %>
<%= f.error_notification %>
<div class="field">
<div id="star-rating"></div>
</div>
<%= f.button :submit, "Rate", class: "button" %>
<% end %>
<script>
$('#star-rating').raty({
path: '/assets/',
scoreName: 'rating[rate]'
});
</script>
Campaign Controller
class CampaignsController < ApplicationController
before_action :find_campaign, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!, except: [:index, :show]
has_scope :free
has_scope :open
has_scope :closed
def index
#campaigns = Campaign.all.order("created_at DESC")
#free_campaign = Campaign.free.first
#open_campaigns = Campaign.open.all
#closed_campaigns = Campaign.closed.all
end
def show
#lyrics = Lyric.where(campaign_id: #campaign.id).order("created_at DESC")
#arts = Art.where(campaign_id: #campaign.id).order("created_at DESC")
#time = Time.now
end
def new
#campaign = current_user.campaigns.build
end
def create
#campaign = current_user.campaigns.build(campaign_params)
if #campaign.save
redirect_to #campaign
else
render 'new'
end
end
def edit
end
def update
if #campaign.update(campaign_params)
redirect_to #campaign
else
render 'edit'
end
end
def destroy
#campaign.destroy
redirect_to root_path
end
private
def find_campaign
#campaign = Campaign.find(params[:id])
end
def campaign_params
params.require(:campaign).permit(:title, :description, :timer, :timer2, :image, :status)
end
end
Error Message is in the Arts#index. Undefined method ratings. First line in my form.
NoMethodError in Arts#index undefined method `ratings' for nil:NilClass
Extracted source (around line #1):
**<%= simple_form_for([#art, #art.ratings.build]) do |f| %>**
<%= f.error_notification %>
<div class="field">
<div id="star-rating"></div>
Presumably Arts index has multiple Art instances, so there is not '#art'.
<% #arts.each do |art| %>
<%= simple_form_for([art, art.ratings.build]) do |f| %>
Etc. Or if there really is only one Art displayed on index, then instantiate that in the controller.
Perhaps also edit this line? I need to see the error log to see where you're seeing the error.
Rating.create(params[:rating].permit(:rate))
I'd break that out into a separate method:
Rating.create(rating_params[:rate))
def rating_params
params.require(:rating).permit(:rate)
end
And I'd check what the javascript 'raty' library is actually inserting into the DOM and whether it really is sending the params you think it is?

Resources