I've been looking for the same problem but not found it.
I'm following this guide, and I'm stuck on setting validations for the text field.
Model (article.rb):
class Article < ActiveRecord::Base
validates :title, presence: true, length: { minimum: 5 }
end
Controller:
class ArticlesController < ApplicationController:
def new
#article = Article.new
end
def create
#article = Article.new(article_params)
if #article.save
redirect_to #article
else
render 'new'
end
end
private
def article_params
params.require(:article).permit(:title, :text)
end
View (new.html.erb):
<%= form_for :article, url: articles_path do |f| %>
<% if #article.errors.any? %>
<div id="error_explanation">
<h2>
<%= pluralize(#article.errors.count, "error") %> prohibited this article from being saved:
</h2>
<ul>
<% #article.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<p>
<%= f.label :title %><br>
<%= f.text_field :title %>
</p>
<p>
<%= f.label :text %><br>
<%= f.text_area :text %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
<%= link_to 'Back', articles_path %>
And when I try to add a new article I open http://localhost:3000/articles/new but instead of the form I see error undefined method errors' for nil:NilClass because of the error in this line <% if #article.errors.any? %>
What am I missing here. Looks like #article is being validated before created? How can I fix it?
index.html.erb:
<h1>Listing articles</h1>
<%= link_to "New article", new_article_path %>
<table>
<tr>
<th>Title</th>
<th>Text</th>
</tr>
<% #articles.each do |article| %>
<tr>
<td><%= article.title %></td>
<td><%= article.text %></td>
</tr>
<% end %>
</table>
You need to call:
<%= form_for #article, url: articles_path do |f| %>
In the first line of new.html.erb
Change the form_for to
<%= form_for(#article) do |f| %>
<% if #article.errors.any? %>
<div id="error_explanation">
<h2>
<%= pluralize(#article.errors.count, "error") %> prohibited
this article from being saved:
</h2>
<ul>
<% #article.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
........
<% end %>
articles_controller.rb
class ArticlesController < ApplicationController
....
end
Related
I'm using Rails 6.0.3.4 and Ruby 2.7.2. Using the Rails getting started tutorial as an example, I'm wondering how to show form validation errors of an associated model.
Show page
<p>
<strong>Title:</strong>
<%= #article.title %>
</p>
<p>
<strong>Text:</strong>
<%= #article.text %>
</p>
<h2>Comments</h2>
<%= render #article.comments %>
<h2>Add a comment:</h2>
<%= render 'comments/form' %>
<%= link_to 'Edit', edit_article_path(#article) %> |
<%= link_to 'Back', articles_path %>
Comments form (this is the form in question)
<%= form_with(model: [ #article, #article.comments.build ], local: true) do |form| %>
<p>
<%= form.label :commenter %><br>
<%= form.text_field :commenter %>
</p>
<p>
<%= form.label :body %><br>
<%= form.text_area :body %>
</p>
<p>
<%= form.submit %>
</p>
<% end %>
Models
class Comment < ApplicationRecord
belongs_to :article
validates :commenter, presence: true
end
class Article < ApplicationRecord
has_many :comments, dependent: :destroy
validates :title, presence: true,
length: { minimum: 5 }
end
For a single model articles form, errors could be shown like this.
<% if #article.errors.any? %>
<div id="error_explanation">
<h2>
<%= pluralize(#article.errors.count, "error") %> prohibited
this article from being saved:
</h2>
<ul>
<% #article.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
How do I show errors for the comments form? When I submit a comment without a commentor, it does not save, so validations are happening, but I'm not sure how to show errors for this type of form.
<% if #???????.errors.any? %> ###### What do I say here to get the comment errors?
<div id="error_explanation">
<h2>
<%= pluralize(#?????.errors.count, "error") %> prohibited
this article from being saved:
</h2>
<ul>
<% #?????.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
1. Create a reusable partial for errors
# app/views/shared/_errors.html.erb
<div class="error_explanation">
<h2><%= pluralize(object.errors.count, "error") %> prohibited
this <%= object.model_name.singular %> from being saved:</h2>
<ul>
<% object.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
And a little helper method:
# app/helpers/application_helper.rb
module ApplicationHelper
# Displays the errors for a model instance if there are any
def display_errors_for(object)
return unless object.errors.any?
render partial: 'shared/errors',
locals: { object: object }
end
end
2. Get the object from the form builder
You can always access the model wrapped by the form builder instance through the #object method instead of using a instance variable:
<%= form_with(model: [ #article, #comment ], local: true) do |form| %>
# ...
<%= display_errors_for(form.object) %>
<% end %>
And like magic you can add errors to any form with a single line.
Do not use #article.comments.build. That will always bind the form to a new instance of comment instead of displaying the errors! It will also remove anything the user entered into the form... Assign the variable in the controller. I have no idea how this snuck its way into the guides.
class ArticlesController < ApplicationController
def show
#article = Article.find(params[:id])
#comment = #article.comments.new
end
end
I have Term and Phrase models and I am adding Nested Resources. I want to get the Term Id for Phraes_term to create a data pair
Example: Term 1 and Phrase 2.
But when you press the new button from show.html.erb term, an error will occur
-->error :PhrasesTermsController#new is missing a template for request formats: text/html
form.html.erb
-(phrases_term).
<%= form_with(model: phrases_term, local: true) do |form| %>
<% if pharases_term.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(pharases_term.errors.count, "error") %> prohibited this phrase from being saved:</h2>
<ul>
<% pharases_term.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= form.label :ID %>
<%= form.number_field_tag :ID %>
</div>
<div class="actions">
<%= form.submit %>
</div>
<% end %>
(phrases_term)
-new.html.erb
<%= render 'form', phrases_term: #phrases_term %>
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_term
#phrases_term.user = current_user
#phrases_term.save
redirect_back(fallback_location: root_path)
end
private
def phrases_term_params
params.require(:phrases_term).permit(:term_id)
end
def set_term
#term = Term.find(params[:term_id])
end
end
routes.rb
resources :terms do
resources :phrases_terms, only: [:create, :destroy, :new]
end
(Term)
Show.html.erb
<td><%= link_to 'New', new_term_phrases_term_path(#term) %></td>
(phrases_term).
_form.html.ebr
<%= form_with(model: phrases_term, local: true) do |form| %>
<% if pharases_term.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(pharases_term.errors.count, "error") %> prohibited this phrase from being saved:</h2>
<ul>
<% pharases_term.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= form.label :ID %>
<%= form.number_field_tag :ID %>
</div>
<div class="actions">
<%= form.submit %>
</div>
<% end %>
(phrases_term)
new.html.erb
<%= render 'form', phrases_term: #phrases_term %>
This means you do not have a app/views/phrases_term(s)/new.html.erb file. I'm unsure if you've namespaced the files under 'phrases_term' or 'phrases_terms'.
Make one in the correct directory, populate it, and it will load.
I'm working on a project in Ruby on Rails (Ruby v.2.2.8, Rails 5.1.4) and have encountered a very strange issue.
For my show method in the controller, I have:
def show
#county = County.find(params[:id])
end
And it works. For update, I have.
def update
#county = County.find(params[:id])
if #county.update(county_params)
redirect_to #county
else
render 'edit'
end
end
In my 'edit', I consistently get an error that #county is nil. The error page indicates that the parameters are being passed as:
{'id'=>4}
as an example. When I use find_by from the rails console, the item is found.
Is there something here I'm missing?
ETA: View Code
<%= form_with model: #county, local: true do |form| %>
<% if #county.errors.any? %>
<div id="error_explanation">
<h2>
<%= pluralize(#county.errors.count, "error") %> prohibited
this county from being saved:
</h2>
<ul>
<% #county.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<p>
<%= form.label :name %><br>
<%= form.text_field :name %>
</p>
<p>
<%= form.label :shortname %><br>
<%= form.text_field :shortname %>
</p>
<p>
<%= form.submit %>
</p>
<% end %>
ETA Routes for Counties:
counties GET /counties(.:format) counties#index
POST /counties(.:format) counties#create
new_county GET /counties/new(.:format) counties#new
edit_county GET /counties/:id/edit(.:format) counties#edit
county GET /counties/:id(.:format) counties#show
PATCH /counties/:id(.:format) counties#update
PUT /counties/:id(.:format) counties#update
DELETE /counties/:id(.:format) counties#destroy
The error occurs at /counties/:id/edit
How is your edit action in your controller?
You should define #county as well
def edit
#county = County.find(params[:id])
end
I'm trying to follow Ryan Bates Polymorphic association tutorial in order to put some comments to my site.
The thing is I have nested resources:
#Nesting Resources
resources :users do
resources :photos do
resources :comments
resources :tags
end
end
So I'm getting an error in my view (photos/show)
undefined method `each' for nil:NilClass
I suppose the problem is in my controller, with comments, that is not defined correctly, but since I have nested resources, I don't know how to do it.
Photos Controller
def show
#photo = Photo.friendly.find(params[:id])
#user = #photo.user
#commentable = #photo
#comments = #commentable.comments
#comment = Comment.new
end
New Comment Partial
<h2>Comments</h2>
<% if #comments.any? %>
<%= render "comments/comments" %>
<% else %>
TodavĂa no hay comentarios
<% if user_signed_in? %>
<%= render "comments/form" %>
<% end %>
<% end %>
Form partial (comments/form)
<%= form_for [#commentable, #comment] do |f| %>
<% if #comment.errors.any? %>
<div class="error_messages">
<h2>Please correct the following errors.</h2>
<ul>
<% #comment.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.text_area :content, rows: 8 %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Comments partial (comments/comments)
<div id="comments">
<% #comments.each do |comment| %>
<div class="comment">
<%= simple_format comment.content %>
</div>
<% end %>
</div>
Your error says undefined method each for nil:NilClass. As you can guess you are calling each on a nil object. Here your #comments is nil and hence giving your trouble.
In your view try something like this:
<div id="comments">
<% if #comments %>
<% #comments.each do |comment| %>
<div class="comment">
<%= simple_format comment.content %>
</div>
<% end %>
<% end %>
</div>
Edit:
So if you look at your code you have #comments till here:
<% if #comments.any? %>
<%= render "comments/comments" %>
<% else %>
#do stuff
<% end %>
it's after you call your partial that your #comment is lost so try this:
<% if #comments.any? %>
<%= render "comments/comments", comments: #comment %>
<% else %>
#do stuff
<% end %>
and then in your view use
<div id="comments">
<% comments.each do |comment| %>
<div class="comment">
<%= simple_format comment.content %>
</div>
<% end %>
</div>
I am trying to realize HABTM checkboxes following this tutorial:
http://www.justinball.com/2008/07/03/checkbox-list-in-ruby-on-rails-using-habtm/
While everything seems to work nicely the updates are not saved to my database.
My controller looks like the following:
class UserrolesController < ApplicationController
before_action :set_userrole
def edit
#projects=Project.all
end
def update
params[:userrole][:project_ids] ||= []
#userrole = Userrole.find(params[:id])
if #userrole.update_attributes(userrole_params)
flash[:notice] = "Settings have been saved."
redirect_to edit_userrole_url(#userrole)
else
flash.now[:error] = #userrole.errors
setup_form_values
respond_to do |format|
format.html { render :action => :edit}
end
end
end
private
def set_userrole
#userrole = Userrole.find(params[:id])
end
def userrole_params
params.require(:userrole).permit(:name, :project_ids)
end
end
My _form.html.erb like this:
<%= form_for(#userrole) do |f| %>
<% if #userrole.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#userrole.errors.count, "error") %> prohibited this person from being saved:</h2>
<ul>
<% #userrole.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="center">
<div class="field">
<%= f.label :Name %>
<%= f.text_field :name %>
</div>
<ul class="checkbox-list">
<% #projects.each do |project| -%>
<li><%= check_box_tag "userrole[project_ids][]", project.id, userrole_edits_project?(project) -%> <%= project.name -%></li>
<% end -%>
</ul>
<div class="actions">
<%= f.submit "Speichern", class: "btn btn-primary" %>
</div>
</div>
<% end %>
So I did everything like in the tutorial, the :name is saved without any problems, but the ids are not saved to the database. There is no error message. Does anybody has an idea what might go wrong? Maybe some missing permission somewhere?
So finally I found a work around for this problem.
I forced the update of project_ids by adding the following line in def update:
#userrole.project_ids=params[:userrole][:project_ids]