Rails error-undefined method `id' for nil:NilClass - ruby-on-rails

I'm trying to get the data from the phrases_term model to the view, but I'm getting an error.
Phrases_term model:
Phrases_term(id, term_id, phrase_id)
phrases_terms_controller.rb
class PhrasesTermsController < ApplicationController
before_action :authenticate_user!
before_action :set_term
def new
#phrases_term = PhrasesTerm.new
end
def create
#phrases_term = #term.phrases_terms.new(phrases_term_params)
if #phrases_term.save
redirect_to term_phrases_term_path(#term, #phrases_term), notice: "Phrases_Term was successfully created"
else
render "new"
end
end
private
def phrases_term_params
params.require(:phrases_term).permit(:term_id, :phrase_id)
end
def set_term
#term = Term.find(params[:term_id])
end
end
Phrases_term show view, show.html.erb:
<div class="container">
<table class="table">
<thead>
<tr>
<th>ID</th>
<th>Phrases_ID</th>
<th>Term_ID</th>
</tr>
</thead>
<tbody>
<tr>
<td><%= #phrases_term.id %></td>
<td><%= #phrases_term.term_id %></td>
<td><%= #phrases_term.phrase_id %></td>
</table>
<%= link_to 'Back', terms_path %> |
<%= link_to 'Edit', edit_term_path %>
</div>
The error I'm getting:
Error: Eundefined method `id' for nil:NilClass

You're getting an undefined method 'id' for nil:NilClass error because your show.html.erb view doesn't know what #phrases_term is. Hence calling the id method on a variable that doesn't exist yet throws an error. You need to define the variable you're using in the right controller under the right action. So adding:
def show
#phrases_term = PhrasesTerm.find(params[:id])
end
in you phrases_terms_controller.rb should solve the error.

Related

NoMethodError (undefined method `destroy' for nil:NilClass):

I am having a problem deleting clients I have created in rails. I am using rails 6.0
"undefined method `destroy' for nil:NilClass"
Controller:
class ClientsController < ApplicationController
before_action :set_client, only: [:show, :edit, :update, :destroy]
def destroy_multiple
#client.destroy(params[:client_ids])
respond_to do |format|
format.html { redirect_to clients_url, notice: 'Client was successfully destroyed.' }
format.json { head :no_content }
end
end
View:
<div class="container">
<div class="table-responsive">
<%= form_tag destroy_multiple_clients_path, method: :delete do %>
<table class="table table-hover">
<thead>
<tr class="table-secondary">
<th scope="col" ><input type="checkbox"></th>
<th>Name</th>
<th>Email</th>
<th>Phone number</th>
<th>Client Type</th>
<th>Nickname</th>
</tr>
</thead>
<tbody>
<% #clients.each do |client| %>
<tr>
<td><%= check_box_tag "client_ids[]", client.id %></td>
<td><%= link_to client.name, client, :class => "clientname" %></td>
<td><%= client.email %></td>
<td><%= client.phone_number %></td>
<td><%= client.client_type %></td>
<td><%= client.nickname %></td>
<% end %>
</tbody>
</table>
</div>
<hr class="featurette-divider">
<%= submit_tag "Delete selected", :class => 'btn btn-primary btn-xs' %>
Console:
Parameters: {"authenticity_token"=>".................==", "client_ids"=>["11"], "commit"=>"Delete selected"}
Completed 500 Internal Server Error in 3ms (ActiveRecord: 0.0ms | Allocations: 1019)
NoMethodError (undefined method `destroy' for nil:NilClass):
app/controllers/clients_controller.rb:65:in `destroy_multiple'
Not sure what I am missing here? How can I pass the ID that shows up in the console to the controller? The examples online show what I am doing but it isn't working for me.
You are using an instance variable that is nil. The destroy method should use the class method
e.g.
instead of
#client.destroy(params[:client_ids])
you could try
Client.destroy(params[:client_ids])
with regards to your question
How can I pass the ID that shows up in the console to the controller?
You are already doing that as evidenced in your stack trace
Parameters: {"authenticity_token"=>".................==", "client_ids"=>["11"], "commit"=>"Delete selected"}
You can clearly see the client_ids parameter is being passed an array, hence the square brackets [] containing a single element with the value of 11 hence the =>["11"]

Pass data from index method of one controller to create of another

I generated a devise model User, and I also have a Conversation controller. I'm showing all users, except the logged in one, and I'm trying to create a new Conversation between user1 and user2, but I get redirected to the index method of the Conversation Controller, not the create one. I understood from this link that making a post from one controller to another is a bad idea Rails: How to POST internally to another controller action?.
I've also tried to make a send_message method inside the Users controller and define it as a post in routes, but I get redirected to the show method of the Users controller.
What is the clean way of doing this?
class UsersController < ApplicationController
before_action :authenticate_user!
def index
#users = User.where.not(id: current_user.id)
end
def send_message
# #conversation = Conversation.new(conversation_params)
# if #conversation.save
#
# end
end
end
index.html.erb
<div class="col-xs-12 col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
<h1> User's index </h1>
<table class="table table-bordered table-hover">
<thead>
<tr>
<th>Email</th>
<th>Created</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% #users.each do |user| %>
<tr>
<td><%= user.email %></td>
<td><%= time_ago_in_words(user.created_at) %> ago</td>
<td>
<div class="btn-group">
<%= link_to 'Send', conversations_path(sender_id: current_user.id, recipient_id: user.id) %>
</div>
</td>
</tr>
<% end %>
</tbody>
</table>
</div>
Edit:
private
def conversation_params
params.require(:conversation).permit(:sender_id, :recipient_id)
end
<ActionController::Parameters {"_method"=>"post", "authenticity_token"=>"394MDmcVVelccU//8ISYeqmk146exYc6G7SrrAhbCA/yQ/K8KTpSn/0EkXlZ4hB/g==", "recipient_id"=>"1", "sender_id"=>"3", "controller"=>"conversations", "action"=>"create"} permitted: false>
By default link_to helper sends GET request. You can do it with adding method: :post to its options.
<%= link_to 'Send', path, method: :post %>
You could redirect to new_converstion_path instead of conversations_path. And link by default sends GET not POST request.

NameError: undefined local variable or method `params' for main:Object from (irb):7

this is the subjects_controller
class SubjectsController < ApplicationController
layout false
def index
#subjects = Subject.order("position ASC")
end
def show
#subject = Subject.find(params[:id])
end
def new
end
def edit
end
def delet
end
end
and this is the 'show.html.erb'
<%= link_to("<< Back to List", {:class => 'index'}) :class => 'back- link)'%>
<div class ="subjects show">
<h2>Show Subject</h2>
<table sammary="Subject detail view">
<tr>
<th>Name</th>
<td><%= #subject.name %></td>
</tr>
<tr>
<th>Position</th>
<td><%= #subject.position %> </th>
</tr>
<tr>
<th>Visible</th>
<td><%= #subject.visible ? 'true': 'flse' %> </th>
</tr>
<tr>
<th>Created</th>
<td><%= #subject.created_at %> </th>
</tr>
<tr>
<th>Updated</th>
<td><%= #subject.updated_at %> </th>
</tr>
</table>
</div>
so when i click on something on the browser i don't get anything and when i did this on rails console
Subject.find(params[:id])
i get this message
NameError: undefined local variable or method `params' for main:Object from (irb):7
params is undefined in your current console context. You're trying to recreate controller code in your console. In the controller, params is automatically assigned according to the incoming HTTP request parameters. In the console params is undefined unless you explicitly assign it. Try this in your console:
params = {id: 1}
Subject.find(params[:id])
It will not throw an error if Subject is in fact an ActiveRecord model.
What are you really trying to accomplish?
If you want to debug your controller, use pry or byebug to get a debug console for the specific context for example:
def edit
binding.pry
#subject = Subject.find(params[:id])
end
Go to the subjects/1/edit path, rails server stops at the break point and you can access the debug console.

Rails undefined method `each' for nil:NilClass...but it is defined

I have searched for hours, tried every possible fix. I cannot make this work. The error is:
*NoMethodError in Articles#index
Showing /Users/myname/blog/app/views/articles/showall.html.erb where line #21 raised:
undefined method `each' for nil:NilClass*
showall.html.erb is a view. It is rendered from the 'article' controller. (both posted below). There is a route to showall, and it works fine. Currently the route is configured as:
get 'article/showall'
But, I have also tried it as:
resources :articles do
get 'showall'
resources :comments
Both routes worked, but neither had an effect on the issue.
There is a method in the controller, its not private:
def showall
#articles = Article.all
end
The offending piece of code in the view is:
<% #articles.each do |article| %>
<tr>
<td><%= article.title.truncate(30) %></td>
<td><%= article.author %></td>
<td><%= article.manufacturer %></td>
<td><%= article.model %></td>
<td><%= article.displacement %></td>`
<% end %>
I actually cut and pasted, the piece of code from the index.html.erb view, where it works perfectly. I have tried every nuance of pluralization I can think of. Any help would be greatly appreciated.
This applicable parts of the controller:
class ArticlesController < ApplicationController
skip_before_action :authorize, only: [:index, :show, :showall]
#Filter used to catch nonlogged in users
before_filter :require_user, :only => [:index]
#method that checks if logged in, sends them to showall if not.
def require_user
unless User.find_by(id: session[:user_id])
render 'showall', :notice => "Please log in to read articles."
end
end
def index
#articles = current_user.articles
end
#should list articles, but throws undefined method 'each' error
def showall
#articles = Article.all
end
Here is the entire view:
<%= render "menu" %>
<body>
<font color="yellow"><%= flash[:notice] %></font>
<br>
<font color="grey">Motorcycle Articles</font>
<%= link_to 'Post New Article', new_article_path %>
<br>
<table>
<tr>
<th>Title</th>
<th>Author</th>
<th>Brand</th>
<th>Model</th>
<th>Displacment</th>
<th>Last Edited On:</th>
<th>Article</th>
</tr>
<% #articles.each do |article| %>
<tr>
<td><%= article.title.truncate(30) %></td>
<td><%= article.author %></td>
<td><%= article.manufacturer %></td>
<td><%= article.model %></td>
<td><%= article.displacement %></td>
<% end %>
</table>
<br>
All articles are property of their respective owners.
</body>
Route is triggering index action, see:
NoMethodError in Articles#index
You get the error because current_user.articles is nil.
You need to make sure Articles#showall is appearing in the log, that will mean that showall method is called.
Do that creating routes:
get '/articles', to: 'Articles#showall'
resources :articles
This is not recommended. There are several parts to improve. But it should make the error disappear.
You are calling render 'showall', which renders the view. This is different than 'redirect_to', which calls the controller action. Since you are setting the value of #articles with a nil value (current_user is not set), you get this error.
To clarify, you need to either redirect_to the 'showall' action or redefine #articles to equal Article.all before rendering the view. Personally I'd redirect.
Modify your routes file
routes.rb
resources :articles do
collection do
get 'showall'
end
end

ActionMailer : NoMethodError in my_class#create undefined method `each' for nil:NilClass

Actionmailer sends out this message when I try to email an index page :
"undefined method `each' for nil:NilClass"
I think I just need to pass the right argument in my controller, I just can't get my head around this. Please help!?
My inventories_controller :
def create
#inventory = Inventory.new(inventory_params)
if #inventory.save
AppMailer.send_inventory(#inventory).deliver
redirect_to inventories_path
else
render :new
end
end
Mailer class:
def send_inventory(inventory)
#inventories = inventory
mail to: inventory.email, from: "marvin8214#gmail.com", subject: "Last Month Sushi Bar Inventory - ITRBA"
end
mail view :
<div class="span5 well">
<% #inventories.each do |inventory| %>
<table>
<tr>
<td><%= inventory.name %> </td>
<td><%= inventory.amount %> </td>
<td><%= inventory.unit %> </td>
</tr>
</table>
<% end %>
</div>
In Mailer class you are passing #inventory
In mailer view however you are accessing #inventories
If you need a collection of model in your view, you require to create a collection instance variable.
UPDATE:
Mailer class:
def send_inventory(inventory)
#inventory = inventory
mail to: inventory.email, from: "marvin8214#gmail.com", subject: "Last Month Sushi Bar Inventory - ITRBA"
end
Mailer View (erb file):
Hi,
Your inventory details:
<table>
<tr>
<td><%= #inventory.name %> </td>
<td><%= #inventory.amount %> </td>
<td><%= #inventory.unit %> </td>
</tr>
</table>
Thanks

Resources