'Ruby On Rails 7.0 invalid? set true in console but not in view
I´m trying to avoid to update an empty name for @post.
I´m beginner in RoR and I don´t understand why in terminal I got @post.invalid? => true but in my view edit.html.erb @post.invalid? => false
posts_controller.rb
class PostsController < ApplicationController
before_action :set_post, :only => [:edit, :show, :update, :destroy]
def index
@posts = Post.all
respond_to do |format|
format.html
format.json { render json: @posts }
end
end
def show
respond_to do |format|
format.html
format.json { render json: @post }
end
end
def edit
end
def update
if @post.update(post_params)
redirect_to posts_path, success: "Post updated"
else
puts @post.invalid? # write true
render 'edit'
end
end
def new
@post = Post.new
end
def create
post = Post.create(post_params)
redirect_to post_path(post.id), success: "Post created"
end
def destroy
@post.destroy
redirect_to posts_path, success: "Post deleted"
end
private
def post_params
params.require(:post).permit(:name, :content)
end
def set_post
@post = Post.find(params[:id])
end
end
post.rb
class Post < ApplicationRecord
validates :name, presence: true
def as_json(options = nil)
super(only: [:name, :id, :created_at] )
end
end
edit.html.erb
<h1>Editer l´article</h1>
<%= @post.invalid? %> <!-- write false -->
<% if @post.invalid? %> <!-- return false -->
<div class="alert alert-danger">
<% @post.errors.full_messages.each do |message| %>
<%= message %>
<% end %>
</div>
<% end %>
<%= form_for @post do |f| %>
<div class="form-group">
<label>Titre de l´article</label>
<%= f.text_field :name, class: 'form-control' %>
</div>
<div class="form-group">
<label>Contenu de l´article</label>
<%= f.text_area :content, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.submit "Modifier l´article", class: 'btn btn-primary' %>
</div>
<% end %>
I´m confused, someone has got an idea ?
Solution 1:[1]
The methods valid? and invalid? all keep running the validation methods every time they are called, and therefore potentially change the state of the model.
If you want to just check for validity when validation has already been run, you should instead use @post.errors.present? or @post.errors.blank? which will never change the status, only read existing errors (that were added in your case when the call to update failed.
Additionally (even if it´s not the case here) calling valid? and invalid? without a context will clear out errors that had been added with validations like validate ..., on: :update.
Solution 2:[2]
The solution I found was a combination of @rewritten´s answer and this one.
So...
<h1>Editer l´article</h1>
<% if @post.errors.present? %>
<div class="alert alert-danger">
<% @post.errors.full_messages.each do |message| %>
<%= message %>
<% end %>
</div>
<% end %>
<%= form_for @post, data: { turbo: false} do |f| %>
<div class="form-group">
<label>Titre de l´article</label>
<%= f.text_field :name, class: 'form-control' %>
</div>
<div class="form-group">
<label>Contenu de l´article</label>
<%= f.text_area :content, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.submit "Modifier l´article", class: 'btn btn-primary' %>
</div>
<% end %>
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | rewritten |
| Solution 2 | J.BizMai |
