Why is my #results Quiz object nil? - ruby-on-rails

I pass the following to the results/index.html.erb view:
def create
#results = Quiz.where(user_id: current_user.id)
redirect_to results_path
end
(I've changed the above action BACK to create).
Then, in my results/index.html.erb view:
<div class="container">
<!-- Example row of columns -->
<div class="row">
<h1>Results page</h1>
<div class="col-md-12">
<p>Eventually a user's results will appear here...</p>
<p><%= #results %></p>
<p><%= #results.inspect %></p>
<p><%= current_user.quiz %></p>
<h4>Quiz Answer</h4>
<p><%= #results.answer1 %></p>
<p><%= #results.answer2 %></p>
<p><%= #results.answer3 %></p>
<p><%= #results.answer4 %></p>
<p><%= #results.answer5 %></p>
<p><%= #results.answer6 %></p>
<p><%= #results.answer7 %></p>
<p><%= #results.answer8 %></p>
</div>
</div>
<footer>
<p><a class="btn btn-default" href="showmetheskills.html" role="button">next</a></p>
</footer>
</div> <!-- /container -->
(I know it's not 'best practise' to have numbered attributes on a Model; ignore that part.)
I get the error:
undefined method 'answer1' for nil:NilClass
Why is #results nil, when I set it IN THE ACTION Rails is asking for?
The Quiz is created in the QuizzesController:
def new
#user = current_user
#quiz = Quiz.create(user_id: current_user.id)
end
Which triggers quizzes/new.html.erb which renders the quiz partial.
What's the problem?

#results is nil because you've done a redirect. Either render the view
def update
#results = Quiz.where(user_id: current_user.id)
render: 'results#index'
end
Or do the redirect and get the results there which would be my preferred option, but I'd question why you're sending them to the update action without updating anything.
def update
redirect_to results_path
end
def ResultsController
def index
#results = Quiz.where(user_id: current_user.id)
end
end
Either way things like #results.answer1 won't work because you have an active record relation. You either need to loop
<% #results.each do |result| %>
<%= result.answer1 %>
<% end %>
Or grab the first result
#results = Quiz.where(user_id: current_user.id).first

In your case #results is an array and you call some answer1, answer2, answer3... methods(that are not defined yet I guess) on array that also does not exists.
Next:
You initialize #results in update action, but expect it to work in resuzlts/index.html.erb.
To show #results in index html you need to load this variable in index action.
Update
If you want your index action to show something, put this line:
#results = Quiz.where(user_id: current_user.id)
into index action
def index
# here
end
and remove answer1, answer2, answer3.... from index.html.erb, they really makes no sense.
Also, index.html.erb should look like this:
<div class="col-md-12">
<p><%= current_user.quiz %></p>
<h4>Quiz Answer</h4>
<% #results.each do |result| %>
<p><%= result.answer %></p>
<% end %>
</div>
this would work only if you have answer defined for result. Hard to say what is what in your app.

Related

NoMethodError in Orders#show , undefined method `grand_total' for nil:NilClass

I'm want to show the grand_total to the show page and i have do a partial file to put in the table, in inside i want to grab the orderproduct data and show to front , but it show me this error. It seem like i didn't define method grand_total, but not sure how to solve it.
Orders controller
class OrdersController < ApplicationController
def supplier
#supplier = Supplier.find(params[:id])
end
def outlet
#outlet = Outlet.find(params[:id])
end
def index
#orders = Order.all
end
def show
#orders = Order.all
#order_products = OrderProduct.all
end
def new
#order = Order.new
#supplier = Supplier.all
#outlet = Outlet.all
#products = Product.all
end
def create
#order = Order.new(order_params)
#supplier_id = Supplier.all
#outlet_id = Outlet.all
if #order.save
product_ids = params[:product_ids]
product_ids.each do |product_id|
OrderProduct.create(order_id: #order.id, product_id: product_id)
end
flash[:success] = "Succesful create!"
redirect_to #order
else
render 'new'
end
end
private
def order_params
params.require(:order).permit(:supplier_id,:quantity, :grand_total, :order_date,
:delivery_date, :delivery_address, :outlet_id)
end
end
_orderproduct.html.erb
<div class="container">
<ul class="responsive-table">
<li class="table-header">
<div class="col col-1">Product</div>
<div class="col col-2">Price</div>
<div class="col col-4">Grand_total</div>
</li>
<% #order_products.each do |order_product| %>
<li class="table-row">
<div class="col col-1" data-label="Product"><%= order_product.product.name %></div>
<div class="col col-2" data-label="Price"><%= order_product.product.price %></div>
<div class="col col-4" data-label="Grand_total"><%= order_product.order.grand_total %></div>
<% end %>
</ul>
</div>
show.html.erb
<% provide(:title)%>
<h2 class="dashboard">Order details</h2>
<div class="row">
<aside class="col-md-4">
<section class="stats">
<%= render 'shared/stats' %>
</section>
<%= render 'orders/orderproduct' %>
<div class="side">
<button class="button-30"><%= link_to "Back to home", home_path %></button>
</div>
</aside>
</div>
Error show in website
The only place in your examples on which you call grant_total is this:
<%= order_product.order.grand_total %>
The error message tells that there is a NoMethodError in Orders#show, undefined method grand_total for nil:NilClass. This means you are calling grant_total on something that is nil and not the type of object you expect. This can only happen when order_product.order returned nil. And that means you have an order_product in your database that doesn't have an order assigned.
There are several ways to fix that, depending on what you want to achieve:
add a validation that ensures that all order_products have an order assigned.
backfill missing orders in the database
exclude order products without associated order when loading or
checking if there is an order and only then outputting its grant total
you can use debugger to see which variable is returning nil value.
Check and work from there.

Why is my instance variable always Nil in my Rails view

The problem that I'm having is that any instance variables that I declare in my show function of Charges Controller, appears as nil in the view. If I set an instance variable to a number, it doesn't even appear in the view. My home function works perfectly with instance variables.
This is my Controller with the Home and Show functions:
class ChargesController < ApplicationController
def home
#products = Product.all
end
def show
#product = Product.find_by(id: params[:id])
end
This is my View for the Show function(show.html.erb):
<h1>Product Details</h1>
<h3> <%= #product.name %> </h3>
<h4> <%= #product.price %> </h4>
<h5> <%= #product.description %> </h5>
This is my view for the Home function that contains the button that directs to the show page(home.html.erb)
<h1>Products</h1>
<% #products.each do |product| %>
<br>
<p> <%= product.name %>: $<%= product.price %> </p>
<p> <%= product.description %> </p>
<%= button_to "Product Details", charge_path(product.id), :method => "get" %>
<br>
<%end%>
error message I'm receiving
find_by method returns nil if it does not find the record. So that means the product id(params[:id]) you searching in your Product model is not found.
You can check it manually in the rails console.
Type rails c in your terminal then try the bellow code
Product.find_by(id: the_id_you_want_to_search)
Alternatively you can use find method. It raises an exception when it does not find the record.
def show
#product = Product.find(params[:id])
end
By default ,its always find by id,So kindly use only..
def show
#product = Product.find params[:id]
end
Moreover,you can check in rails console using rails c to verify that the record is present with that id using,for example Product.find 18.
Also check the url which should match with your routes..for example../users/:id for get request Only mapped to users#show action.
Get local copy of your routes using rake routes > path.text and use it as reference
In your home.html.erb try change this
<%= button_to "Product Details", charge_path(product.id), :method => "get" %>
to
<%= link_to "Product Details", charge_path(product.id) %>
Then if it does not work, try to raise the params or the instance in your show method
def show
raise params.inspect
#product = Product.find params[:id]
end
or
def show
#product = Product.find params[:id]
raise #product.inspect
end
Those were some simple ways to check whats happening in your code.

Rails retrieving all records in show controller

In my rails category show controller for categories I have it setup like this
def show
#categories = Category.find_by(params[:name])
end
But when I visit this controller it returns all records of products found in the category instead of single category.
Here is the code in my view controller for category
<div class="grid">
<% #categories.products.each do |product| %>
<%= link_to product_path(id: product.slug, category_name: product.category.name), class: "card" do %>
<div class="product-image">
<%= image_tag product.productpic.url if product.productpic? %>
</div>
<div class="product-text">
<h2 class="product-title"> <%= product.name %></h2>
<h3 class="product-price">£<%= product.price %></h3>
</div>
<% end %>
<% end %>
</div>
What am i doing wrong here?
First of all, for security purposes, you should never trust the params hash to retrieve records. Rails will "make the data safe" if you use a hash as your arguments. Use this code below:
def show
#category = Category.find_by(name: params[:name])
end
Second, usually on a show page, you only want to retrieve one record and therefore the variable should be named as singular. I corrected that above.
Third, it helps if you use proper indenting when posting examples. It makes it easier for us to help you.
Fourth, the line below (I changed #categories to #category) is basically saying: "Now that I have this single category, find all the products associated with it in the products table and put them into the |product| variable for iteration"
<% #category.products.each do |product| %>
I'm not sure what you want to do with the category, but if you keep this line of code, it will always show you all the products. Maybe you only want to show the most recent 3, in which case you could do something like this:
In your controller:
def show
#category = Category.find_by(name: params[:name])
#recent_products = #category.products.order(created_at: :desc).limit(3)
end
In your view:
<div class="grid">
<% #recent_products.each do |product| %>
<%= link_to product_path(id: product.slug, category_name: product.category.name), class: "card" do %>
<div class="product-image">
<%= image_tag product.productpic.url if product.productpic? %>
</div>
<div class="product-text">
<h2 class="product-title"> <%= product.name %></h2>
<h3 class="product-price">£<%= product.price %></h3>
</div>
<% end %>
<% end %>
</div>
You can do this way
in your controller you can write this code
def show
#category = Category.find_by_name(params[:name])
end
and in your view it will work
<div class="grid">
<% #category.products.each do |product|%>
// place your code what you want to display
<% end %>
</div>
I hope it would help you and still if you have any concern please let me know.

Raw Database content showing up in Rails View

You can see here that it seems like the raw contents of my DB are being printed to the page. I can't see anywhere in my code why there would be the raw output of the db printed to the view. Here is the code for the index view:
<div class="main">
<div="messages">
<%=#messages.each do |t|%>
<h2 class="subject"><%=t.subject%></h2>
<p class="content"><%=t.content%></p>
<% end %>
<%=link_to "Create Message", edit_path%>
</div>
</div>
The Create Form/View:
<div class="formWrapper">
<%= form_for #messages do |t|%>
<div class ="Inputs">
<%=t.text_field :subject%><br>
<%=t.text_area :content%>
<div class="submit">
<%=t.submit "Submit"%>
</div>
<%end%>
</div>
</div>
The Controller:
class MessagesController < ApplicationController
def index
#messages=Message.all
end
def new
#messages=Message.new
end
def create
#messages = Message.new(message_params)
if #messages.save
redirect_to '/'
else
render 'new'
end
end
private
def message_params
params.require(:message).permit(:content, :subject)
end
end
you don't need the = here: <%=#messages.each do |t|%>, the equals sign is telling erb to show every message on the view.
<% %>
Will execute Ruby code with no effect on the html page being rendered. The output will be thrown away.
<%= %>
Will execute Ruby code and insert the output of that code in place of the <%= %>
example...
<% puts "almost" %> nothing to see here
would render as
nothing to see here
however
<%= puts "almost" %> nothing to see here
would render as
almost nothing to see here
Look at <% %>(without equal) in ruby erb means?

undefined method `comments' for nil:NilClass - listing for a specific user

There are posts, comments & users. I want to post number of comments for a specific user in comments list on Post show page. I know I need to define #user, but I don't know how to define it, so that it shows specific number for every user. User is author of the comment.
Post controller
def show
#post = Post.find(params[:id])
#comment = Comment.new
#comments = Post.find(params[:id]).comments.order(created_at: :desc)
#user = ???
end
Post /show action - error is for - #user.comments.count
<div class="row">
<% #comments.each do |comment| %><br>
<div class="col-sm-4"> <%= link_to comment.user.name, user_path(comment.user) %> <br>
<%= image_tag(comment.user.smallimage) %><%= #user.comments.count %>
</div>
<div class="col-sm-8"> <b><%= comment.title %>:</b>
<div>
<% if comment.content.length > 250 %>
<%= truncate(comment.content, length: 250) %>
<%= link_to_function '...Read more', "$(this).parent().html('#{escape_javascript comment.content}')" %>
<% else %>
<%= comment.content %>
<% end %>
</div>
</div>
<% end %>
</div>
If you define an #user you will only have one user or a group of users that doesn't relate to your comments. You don't need it. You can just use the relationship between user and comment like this:
<%= comment.user.comments.count %>
Note that this will run a database query for each comment to get the total comment count for that user. For performance reasons you may want to use a counter cache for this instead.
If you defined the association in the post model belongs_to :user then you can probably do #user = #comment.user
But, if that's the case then you can call that from the view with #comment.user.name or something like that.
I'd like to see the whole codebase if you've pushed to GitHub.

Resources