Render partial in new site, rails - ruby-on-rails

Ok so far i created an new controller with:
rails g controller home settings
In the settings.html.erb i want to display an partial so that i simply added one line:
<%= render "categories/index", :locals => {:categories => #categories} %>
So my categories/_index.html.erb looks like this, and worked:
<% for category in #categories do %>
<tr>
<td><%= category.typ %></td>
<td><%= link_to "Löschen", category,:class => 'btn btn-mini btn-danger', method: :delete, data: { confirm: 'Sind sie sicher?' } %></td>
</tr>
<% end %>
<tr>
<%= form_for Category.new do |f| %>
<td> <%= f.text_field :typ, :class => "input-small" %></td>
<td><%= f.submit "Speichern", :class => 'btn btn-mini btn-success' %></td>
</tr>
<% end %>
</table>
</div>
But now when i open localhost:3000/home/settings i get the error:
NoMethodError in Home#settings
Showing C:/Sites/rublesql/app/views/categories/_index.html.erb where line #10 raised:
undefined method `each' for nil:NilClass
Extracted source (around line #10):
7: <th></th>
8: </tr>
9:
10: <% for category in #categories do %>
11: <tr>
12: <td><%= category.typ %></td>
So my question is what did i wrong?
Categories controller:
class CategoriesController < ApplicationController
def index
#categories = Category.all
end
def destroy
#category = Category.find(params[:id])
#category.destroy
redirect_to categories_path
end
def create
#category = Category.new(params[:category])
#category.save
redirect_to categories_path
end
end

It means the #categories instance variable hasn't been set.
Check in your controller that it sets #categories = xx.

Three things I notice:
You're mixing notations with the partial. Previously you would do, render partial: "x", locals: {}, now you can drop the partial key and just send the view path in, but if you choose to do this you also remove the locals: key:
<%= render "categories/index", {categories: #categories} %>
Also:
{:categories => #categories} will make categories your local, not #categories.
However, your instanced #categories should pass through as well, so it isn't your issue.
Finally:
#categories isn't set (or if it is, it becomes nil). Either make sure your controller correctly assigns it, or otherwise check .nil? or for .present? before attempting to loop through them.

Related

How to use Rails 5.2 form_with to trigger a specific action?

My application needs to duplicate a Skill (from skills index) as many times the user needs it in his cart. So I decided to trigger the add-to-cart method of the skills_controller when the related form, including the number of duplicates and the Skill's id, is submitted. For this purpose, I added counter to the strong parameters of skills_controller.
Unfortunately, I am missing something to correctly setup the form: when submitted, it triggers the create method. Here is the code:
routes.rb extract
resources :skills, :path => "variables" do
resources :values_lists
member do
post :add_to_cart
get :create_values_list
get :upload_values_list
get :remove_values_list
end
collection do
get :index_all
end
end
skills_controller.rb method
def add_to_cart
#template_skill = Skill.find(params[:id])
iterations = params[:skill][:counter].to_i
until iterations == 0
#skill = #template_skill.deep_clone include: [:translations, :values_lists]
#skill.business_object_id = session[:cart_id]
#skill.template_skill_id = #template_skill.id
#skill.code = "#{#template_skill.code}-#{Time.now.strftime("%Y%m%d:%H%M%S")}-#{iterations}"
#skill.is_template = false
#skill.save
iterations -= 1
end
#business_object = BusinessObject.find(session[:cart_id])
redirect_to #business_object, notice: t('SkillAdded2BO') # 'Skill successfully added to business object'
end
index.html.erb table content
<tbody>
<% #skills.each do |skill| %>
<tr data-href="<%= url_for skill %>">
<% if not session[:cart_id].nil? %>
<td>
<%= form_with model: #skill, :action => "add_to_cart", :method => :post, remote: false do |f| %>
<%= f.text_field :counter, value: "1", class: "mat-input-element", autofocus: true %>
<button type="submit" class="mat-icon-button mat-button-base mat-primary add-button" title="<%= t('AddToUsed') %>">
<span class="fa fa-plus"></span>
</button>
<% end %>
</td>
<% end %>
<td class="no-wrap"><%= skill.code %></td>
<td><%= link_to skill.translated_name, skill %></td>
<td><%= link_to translation_for(skill.parent.name_translations), skill.parent %></td>
<td><%= skill.responsible.name %></td>
<td><%= skill.updated_by %></td>
<td class="text-right"><%= format_date(skill.updated_at) %></td>
</tr>
<% end %>
</tbody>
Thanks a lot for your help!
According to this form helpers guide, the syntax you used doesn't exist
form_with model: #model, action: :custom_action
So in this case, you have to specify the url parameter for form_with to make it works.
<%= form_with model: #skill, url: :add_to_cart_skill_path(#skill), method: :post, remote: false do |f| %>

Link_to another view ruby on rails

I am trying to use the link_to feature to link one view to another.
The view i am calling link_to is app/views/instructors/show.html.erb and that snippet of code looks like this (namely, the second to last line of it)
<% provide(:title, #instructor.login) %>
<% courses = Course.where(:instructor_ID => #instructor.id) %>
<div class="span2">
<h1 align=center ><%= #instructor.login %></h1>
<%= link_to "Add course", new_course_path(:instructor_ID\
=> #instructor.id), :class => "btn" %>
<br>
<br>
<%= link_to "Remove course", delete_course_path(courses), :class => "btn"%>
</div>
The view I am trying to link to is is app/views/courses/show_all.html.erb and looks like this:
<% #courses.each do |course| %>
<tr>
<td><%= course.course_name %></td>
<td><%= course.instructor_ID %></td>
<td><%= link_to 'Show', course %></td>
<td><%= link_to 'Edit', edit_course_path(course) %></td>
<td><%= link_to 'Destroy', course, :method => :delete, :data => { :confirm => 'Are you sure?' } %></td>
</tr>
delete_course_path routes to app/views/courses/show_all.html.erb shown above. When I try the code above, I get the following error:
undefined method `each' for nil:NilClass
At this line:
<% #courses.each do |course| %>
Any ideas what i'm missing in my link_to?
In your show_all action, you should define a #courses instance variables. This is
<% courses = Course.where(:instructor_ID => #instructor.id) %>
not passed to show_all.html.erb.
An instance variables is a variable passed from action of controller to the view corresponding.
I suppose when you show page of instructor, your route will like this: /instructors/:id, so maybe in your show_all action of instructor controller, you need something like:
def show_all
#courses = Course.where(instructor_ID: params[:id])
render 'courses/show_all'
end
This means that #courses is nil. Did you set it in your show_all action of your controller? E.g.
def show_all
#courses = Course.all
end
Also, in your show view, you set courses to a collection of Course objects, but your "Remove course" link looks like you only want to delete one course. Why do you use the delete_course route to link to your show_all view?

undefined method 'each for nil:NilClass

I am working on a system that is currently in use and an error for a feature that is not very often used has come up.
NoMethodError in Offer_receipts#index
Showing /Users....../app/views/offer_receipts/index.html.erb where line #8 raised:
undefined method `each' for nil:NilClass
Extracted source (around line #8):
5: <th>Patron</th>
6: <th>One Time Offer</th>
7: </tr>
8: <% for offer_receipt in #offer_receipts %>
9: <tr>
10: <td><p> popld</p></td>
11: <td><%= offer_receipt.patron_id %></td>
This error happens when this partial render page is currently being displayed:
<h2>Offers</h2>
<div id="offers">
<% if #offers.count > 0 %>
< % #offers.each do |o| %>
<%= show_one_time_offer(o, #patron) %>
<% end %>
<% else %>
<strong>There are no offers currently available</strong>
<% end %>
</div>
Once the one time offer is clicked on, this page is loaded and this is the page the error happens on:
index.html.erb
<% title "Offer Receipts" %>
<table>
<tr>
<th>Patron</th>
<th>One Time Offer</th>
</tr>
<% for offer_receipt in #offer_receipts %>
<tr>
<td><%= offer_receipt.patron_id %></td>
<td><%= offer_receipt.one_time_offer_id %></td>
<td><%= link_to "Show", offer_receipt %></td>
<td><%= link_to "Edit", edit_offer_receipt_path(offer_receipt) %></td>
<td><%= link_to "Destroy", offer_receipt, :confirm => 'Are you sure?', :method => :delete %></td>
</tr>
<% end %>
</table>
<p><%= link_to "New Offer Receipt", new_offer_receipt_path %></p>
and here are two other files that define the methods and scope of the One Time Offer receipt
offer_receipt.rb
class OfferReceipt < ActiveRecord::Base
belongs_to :patron
belongs_to :one_time_offer
validates :patron, :presence=>true
validates :one_time_offer, :presence=>true
require 'offer_receipt_validator.rb'
validates_with OfferReceiptValidator
end
offer_receipts_controller.rb
class OfferReceiptsController < ApplicationController
def create
begin
#patron = Patron.find(params[:patron])
rescue ActiveRecord::RecordNotFound
flash[:error] = "You must provide a patron for an offer receipt"
redirect_to root_url
return
end
#offer_receipt = OfferReceipt.new(:patron_id=>params[:patron], :one_time_offer_id=>params[:one_time_offer])
if #offer_receipt.save && #patron
redirect_to #patron, :notice => "Recorded offer receipt"
else
flash[:error] = "There was a problem saving your offer receipt"
redirect_to #patron
end
end
end
There are other index.html.erb files for listing other things with the exact same for each loop, and they are working fine. I also checked the database and there are over 2000 rows so that can't be the issue.
Your instance variable, #offer_receipt is not set in your #index controller action.
You should add the #index action. Something like this should work:
class OfferReceiptsController < ApplicationController
def index
#offer_receipts = OfferReceipt.all
end
end
You can also add additional logic in the #index action. You might want to scope the instance variable to a current_user, for example.
#offer_receipts = OfferReceipt.where(:user_id => current_user.id)

Rails RuntimeError: "Called id for nil". Rails is telling me that the instance variable I'm passing in through params[:id] is null [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
EDIT2: [SOLVED] The "create" method in the controller file does not "end" until after the "edit" method. I can't answer my own question until 8 hours afterwards, however.
EDIT: It's been brought to my attention that this may be a problem with my routes.rb file. Which is just below.
routes.rb
SimpleCms::Application.routes.draw do
root :to => "subjects#list"
match ':controller(/:action(/:id))(.:format)'
end
Essentially this is an #instance_variable issue. More specifically an #instance_variable[:id => nil] problem. Somehow I'm passing a nil (null) :id (primary key) value to rails but the edit button which I'm clicking on (the last file in this list is the list.html.erb file which contains the button that takes you to edit.html.erb) is supposed to be passing the :id value corresponding to the given subject on the list page.
So here is the error message from the browser first of all:
RuntimeError in Subjects#edit
Showing C:/Users/davo/Desktop/RailsProjects/simple_cms/app/views/subjects/edit.html.erb where line #6 raised:
Called id for nil, which would mistakenly be 4 -- if you really wanted the id of nil, use object_id
Extracted source (around line #6):
3: <div class="subject edit">
4: <h2>Update Subject</h2>
5:
6: <%= form_for(:subject, :url => {:action => 'update', :id => #subject.id}) do |f| %>
7:
8: <table summary="Subject form fields">
9: <tr>
Rails.root: C:/Users/davo/Desktop/RailsProjects/simple_cms
Application Trace | Framework Trace | Full Trace
app/views/subjects/edit.html.erb:6:in `_app_views_subjects_edit_html_erb__829468061_51428148'
Request
Parameters:
{"id"=>"1"}
Here is the controller ("subjects_controller.rb") so you can see the instance variable stuff. The edit and update methods are on the bottom
**All the other methods which call params[:id] are working. It's possible that there is nothing wrong with the controller and that it's just the view. In particular, on that view, the #subject versus :subject versus subjects.method stuff...there seems to be something wrong with that syntax.
class SubjectsController < ApplicationController
def list
#subjects = Subject.order("subjects.position ASC")
end
def index
list
render('list')
end
def show
#subject = Subject.find(params[:id])
end
def new
#subject = Subject.new(:name => 'default')
end
def create
#instantiate a new object using form params
#subject = Subject.new(params[:subject])
#save the subject
if #subject.save
redirect_to(:action => 'list')
#if save succeeds redirect to list action
else
#if save fails, redisplay form
render('new')
end
def edit
#subject = Subject.find(params[:id])
end
#passing an #instancevariable inside of a {hash}...is there anything odd about that?
#I'm just trying to inspire you guys -->
#
#I have a hunch that the :syntax/#syntax/#{etc} involving params, :id and
#:subject could be the root of this issue...just a hunch
#
def update
#Find object using form parameters
#subject = Subject.find(params[:id])
#Update the object
if #subject.update_attributes(params[:subject])
redirect_to(:action => 'show', :id => #subject.id)
else
render('edit')
end
end
end
end
Lastly, here is edit.html.erb
<%= link_to("<< Back to List", {:action => 'list'}, :class => 'back-link') %>
<div class="subject edit">
<h2>Update Subject</h2>
<%= form_for(:subject, :url => {:action => 'update', :id => #subject.id}) do |f| %>
<table summary="Subject form fields">
<tr>
<th>Name</th>
<td><%= f.text_field(:name) %></td>
</tr>
<tr>
<th>Position</th>
<td><%= f.text_field(:position) %></td>
</tr>
<tr>
<th>Visible</th>
<td><%= f.text_field(:visible) %></td>
</tr>
</table>
<tr>
<td><%= f.submit 'Update Subject' %></td>
</tr>
<% end %>
</div>
EDIT:
here is the list.html.erb file, which contains the link that points to the edit.html.erb file, which, currently, does not open and displays the error message.
<html>
<div class="subject list">
<h2>Subjects</h2>
<!--- header row with all the different attributes --->
<table class="listing" summary="Subject list">
<tr class="header">
<th>#</th>
<th>Subject</th>
<th>Visible</th>
<th>Pages</th>
<th>Actions</th>
</tr>
<!-- this is the beginning of a loop, that ends way down there -->
<% #subjects.each do |subject| %>
<tr>
<td><%= subject.position %></td>
<td><%= subject.name %></td>
<td class="center"><%= subject.visible ? 'Yes' : 'No' %></td>
<td class="center"><%= subject.pages.size %></td>
<td class="actions">
<%= link_to("Show", {:action => 'show', :id => subject.id}, :class => 'action show') %>
<%= link_to("Edit", {:action => 'edit', :id => subject.id}, :class => 'action edit') %>
<%= link_to("Delete", '#', :class => 'action delete') %>
</td>
<% end %>
</tr>
</table>
<%= button_to "Create New Subject", {:action => 'new'}, {:class => "buttonTo"} %>
</div>
</html>
EDIT:
- Let me know if you need to see a particular model.rb file. In my models folder I have "subject.rb", "section.rb", "section_edit.rb", "page.rb" and "admin_user.rb" if you need to see any of those. I'm kind of stumped on this one so maybe they'd be useful. They all contain a bunch of schema (has_many, belongs_to, etc) instructions and a few custom console calls.
= form_for(#subject, :as => :subject, .....
#subject is not nil, because find raises exception if no record have been found
I made a typo when doing the some of the def/end syntax in the controller. I think it was 'def create', I didn't end it.

ActiveRecord::RecordNotFound Error in Lynda Rails Training (Ch 9 - Delete/Destroy)

I'm new, so forgive my complete ignorance. I'm on Rails 3.2.3 and am doing the Lynda Ruby on Rails Essentials course. I've completed the chapter listed in the title, but am getting an error page after confirming the delete button. Here is a video to show you the error in action.
I've reviewed the following docs to confirm that I've not made typing errors.
Here is my list.html.erb
<div class="subject list">
<h2>Subjects</h2>
<%= link_to("Add New Subject", {:action => 'new'}, :class => 'action new') %>
<table class="listing" summary="Subject List">
<tr class="header">
<th> </th>
<th>Subject</th>
<th>Visible</th>
<th>Pages</th>
<th>Actions</th>
</tr>
<% #subjects.each do |subject| %>
<tr>
<td><%= subject.position %></td>
<td><%= subject.name %></td>
<td class="center"><%= subject.visible ? 'Yes' : 'No' %></td>
<td class="center"><%= subject.pages.size %></td>
<td class="actions">
<%= link_to("Show", {:action => 'show', :id => subject.id}, :class => 'action show') %>
<%= link_to("Edit", {:action => 'edit', :id => subject.id}, :class => 'action edit') %>
<%= link_to("Delete", {:action => 'delete', :id => subject.id}, :class => 'action delete') %>
</td>
</tr>
<% end %>
</table>
Here is my delete.html.erb
<%= link_to("<< Back to List", {:action => 'list'}, :class => 'back-link') %>
<div class="subject delete">
<h2>Delete Subject</h2>
<%= form_for(:subject, :url => {:action => 'destroy'}, :id => #subject.id) do |f| %>
<p>Are you sure you want to permanently delete this subject?</p>
<p class="reference-name">Subject name: <%= #subject.name %></p>
<div class ="form-buttons">
<%= submit_tag("Delete Subject") %>
</div>
<% end %>
</div>
Here is my subjects_controller.rb
class SubjectsController < ApplicationController
def index
list
render('list')
end
def list
#subjects = Subject.order("subjects.position ASC")
end
def show
#subject = Subject.find(params[:id])
end
def new
#subject = Subject.new
end
def create
# Instantiate a new object using form parameters
#subject = Subject.new(params[:subject])
# Save the object
if #subject.save
# If save succeeds, redirect to the list action
redirect_to(:action => 'list')
else
# If save fails, redisplay the form so user can fix problems
render('new')
end
end
def edit
#subject = Subject.find(params[:id])
end
def update
# Find object using form parameters
#subject = Subject.find(params[:id])
# Update the object
if #subject.update_attributes(params[:subject])
# If save succeeds, redirect to the list action
redirect_to(:action => 'show', :id => #subject.id)
else
# If save fails, redisplay the form so user can fix problems
render('edit')
end
end
def delete
#subject = Subject.find(params[:id])
end
def destroy
Subject.find(params[:id]).destroy
redirect_to(:action => 'list')
end
end
Here is the resulting error page referenced in the video above.
If I can get some help in understanding why I can't get this properly delete the file, that would be great.
I'm sorry, I have never heard of "Lynda Ruby on Rails Essentials course" but I can see from your posted code that your delete form looks totally messed up, you have a form_for but you are using a submit_tag! That doesn't make sense. The problem is that if you look in your log file you will see that the params passed in to the delete action do not include an id therefore when you use #subject = Subject.find(params[:id]) you will get the error you are seeing.
The solution - change the submit_tag to f.submit OR change the form_for to a form_tag and make sure the correct route is called, that way the id should be passed back through the params hash.
Your log file stack trace is ALWAYS your very best friend, learn to understand it ASAP and you will find your life a lot easier.
UPDATE
For a large number of reasons I think your best option would be to change your form to look like this
<%= link_to("<< Back to List", {:action => 'list'}, :class => 'back-link') %>
<div class="subject delete">
<h2>Delete Subject</h2>
<p>Are you sure you want to permanently delete this subject?</p>
<p class="reference-name">Subject name: <%= #subject.name %></p>
<div class ="form-buttons">
<%= button_to "Delete", subject_path(#subject), method: :delete %>
</div>
</div>
The reason the first way did not work is because you missed the leading opening tag "<" which is why the text got displayed instead of the button
you don't need the form, you are entering no data so just use the button_to and tell it to go to the delete action.
I haven't tested the code but it should be fine

Resources