Displaying simple search form - ruby-on-rails-4.1

I still new with RoR and i am trying to add a simple search form to my app. This is how i proceed.
class BooksController < ApplicationController
before_action :set_book, only: [:show, :edit, :update, :destroy]
def index
if params[:search]
#users = User.search(params[:search]).order("created_at DESC")
else
#users = User.order('created_at DESC')
end
end
def new
#book= Book.new
end
def create
#book= Book.new(books_params)
if #book.save
redirect_to admin_manage_path
else
render 'new'
end
end
def list
#books= Book.all
end
def show
end
private
def set_book
#book = Book.find(params[:id])
end
def books_params
params.require(:book).permit(:title, :author, :price, :resume)
end
end
my book model
class Book < ActiveRecord::Base
def self.search(query)
where('title like ?', "%#{query}%")
end
end
my list.html.erb where the search form is shown:
<% if current_user.present? %>
Welcome <%= current_user.pseudo %> | <%= link_to 'Déconnexion' , user_logout_path %>
<% end %>
<br>
<%= form_tag(books_path, :method => "get", id: "search-form") do %>
<%= text_field_tag :search, params[:search], placeholder: "Search books" %>
<%= submit_tag "Search", :name => nil %>
<% end %>
<br>
and my index.html.erb where the search result should be shown:
<% #books.each do |b| %>
<%= b.title %>
the error diplayed is :
Couldn't find Book without an ID
and i do not understand what it refer to controller#show method
ActiveRecord::RecordNotFound in BooksController#show

I found the error's source, i forgot to specify the appropriate route

Related

rails turbo_stream is not working on a rails 7 application

I am trying to submit a form and return a turbo_stream on a rails 7.0 application.
In my form I have the following.
<%= form_with url: "/request_trial", method: :post, format: :turbo_stream do |form| %>
<%= form.label :name, I18n.t('marketing.form.name'), class: 'form-label required' %>
<%= form.text_field :name, class:"form-control", required: true %>
<%= form.submit I18n.t('marketing.form.send'), class: 'btn btn-trial' %>
<% end %>
In my controller I have the following
respond_to do |format|
format.turbo_stream do |format|
render turbo_stream: turbo_stream.replace(:'marketing-request-trial-form',
partial: 'marketing/request_trial')
end
end
This gives me an error ActionController::UnknownFormat
Although I have a format specify in my form, it seems that format is html when I submit the form.
I can see where this is coming from, on my request headers I have the following
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
I need to add on the request header the text/vnd.turbo-stream.html type, how can I do that?
you need emphasis the format type
format.turbo_stream do
render turbo_stream: turbo_stream.replace(#article, partial: 'welcome/form')
end
you can reference Rails Completed 406 Not Acceptable in 64ms
welcome_controller.rb
class WelcomeController < ApplicationController
def index
#article = Article.first
end
def update_article
#article = Article.find(article_params[:id])
respond_to do |format|
if #article.update(article_params)
format.turbo_stream do
render turbo_stream: turbo_stream.replace(#article, partial: 'welcome/form')
end
end
end
end
def article_params
params.require(:article).permit(:id,:title, :body)
end
end
index.html.erb
<h1>Welcome ! This is a tutorial about Rails forms</h1>
<%= turbo_frame_tag dom_id(#article) do %>
<%= form_with model: #article, url: update_article_path, method: :post, format: :turbo_stream do |form| %>
<%= form.text_field :id %>
<%= form.text_field :title %>
<%= form.text_field :body %>
<%= form.submit "Update" %>
<% end %>
<% end %>
_form.html.erb
<%= turbo_frame_tag dom_id(#article) do %>
<h1>New Book</h1>
<div class="card card-body">
<label>title</label>
<input value="<%= #article.title %>">
</div>
<% end %>
schema.rb
ActiveRecord::Schema[7.0].define(version: 2022_02_16_084944) do
create_table "articles", force: :cascade do |t|
t.string "title"
t.text "body"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
end
The reason you got ActionController::UnknownFormat exception is that you only respond turbo_stream format, but the actual format is HTML(You didn't pass the correct format).
Solution 1
format: :turbo_stream is assumed to be passed as an argument of URL helpers rather than form helpers. For example:
some_url_helper_path(format: :turbo_stream)
In your literal URL case should be:
<%= form_with url: "/request_trial.turbo_stream", method: :post do |form| %>
Solution 2
Solution 1 can make controller respond turbo_stream correctly. But due to the bug, you might see turbo_stream as plain text instead of replacing views. Before a new version of Turbo js release, you can add a hidden field to forms manually:
<input type="hidden" name="format" value="turbo_stream">

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 ?
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.
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 %>

Rails nested resource not updating

I have two forms (Clients and Posts).
For my client, I can create/show/update/delete my client with no problem.
For my post, I can create/show and delete. But for some reason it does not update.
In the update form, after I make the changes and click on the "Update Post" button, it shows as if it was updated, but when I check the post, it still has the old data. I do not know what could be wrong.
Here is part of my code:
My client.rb
class Client < ActiveRecord::Base
has_many:posts, dependent: :destroy
end
My post.rb
class Post < ActiveRecord::Base
belongs_to :client
end
My client controller
class ClientsController < ApplicationController
before_action :authenticate_user!
before_action :find_client, only:[:show, :edit, :update]
... is working fine
My post controller
class PostsController < ApplicationController
before_action :authenticate_user!
before_action :find_client
before_action :find_post, only:[:show, :edit, :update, :destroy]
def index
#client = Client.find(params[:client_id])
#posts = #client.posts
end
def new
#post = #client.posts.new
end
def create
#post = #client.posts.create(post_param)
flash[:notice]="Post Created Sucessfully."
redirect_to client_post_path(#client, #post)
end
def update
# #post = #client.posts.find(params[:id])
if #post.save
flash[:notice]="Post Updated Sucessfully"
redirect_to client_post_path(#client, #post)
else
render 'edit'
end
end
def destroy
#post.destroy
flash[:notice]="Post Deleted Sucessfully"
redirect_to client_posts_path(#client)
end
private
def find_client
#client = Client.find(params[:client_id])
end
def find_post
#post = Post.find(params[:id])
end
def post_param
params.require(:post).permit(:post_name, :title, :body)
end
end
My 'index.html.erb' for my posts
<h2>Posts of <%=#client.name%></h2>
<div class="NewItem">
<p><%= link_to "NEW POST", new_client_post_path(#client)%></p>
</div>
<div class="ListPosts">
<table border="1">
<th><td><b>Post Name</b></td><td><b>Post Title</b></td></th>
<% #client.posts.each do |p|%>
<tr>
<td><%= link_to "Edit", edit_client_post_path(#client,p) %> | <%=link_to "Delete", [#client, p], method: :delete, data:{Confirm: "Confirm Data Exclusion?"}%></td>
<td><%=p.post_name%></td>
<td><%=p.title%></td>
</tr>
<% end %>
</table>
</div>
My partial '_editform.html.erb'
<h2>Edit Post of <%=#client.name%></h2>
<%= form_for [#client, #post] do |f|%>
<%=f.label:post_name %><br>
<%=f.text_field:post_name %><br>
<%=f.label:title %><br>
<%=f.text_field:title %><br>
<%=f.label:body %><br>
<%=f.text_area:body %><br>
<%=f.submit %><br>
<% end %>
My 'edit.html.erb'
<%= render 'editform'%>
Your update action in your post controller didn't pass in the new submitted params to save. You need to pass in the new params like
def update
#post = #client.posts.find(params[:id])
if #post.update(post_params)
flash[:notice]="Post Updated Sucessfully"
redirect_to client_post_path(#client, #post)
else
render 'edit'
end
end
private
def post_params
params.require(:post).permit(:post_name, :title, :body)
end
something like this, so you can update your post.

Improper form validation

I'm running into a strange issue. Here is the controller code regarding the flash:
def create
user = User.find_by(email: params[:email])
if user && user.authenticate(params[:password])
session[:user_id] = user.id
redirect_to root_path, notice: "Signed in!"
else
flash.now[:error] = 'Your email or password is incorrect!'
render "new"
end
end
Here is the associated view code:
<% if flash.now[:error] %>
<%= label_tag :email %>
<%= text_field_tag :email, nil, class: "error"%>
<%= label_tag :password %>
<%= password_field_tag :password, nil, class: "error" %>
<% else %>
<%= label_tag :email %>
<%= text_field_tag :email%>
<%= label_tag :password %>
<%= password_field_tag :password%>
<% end %>
The error class should result in the input fields turning red. However, they currently briefly flash red and then the page is rendered. What can I be doing better here?
Thanks
From the docs:
When you need to pass an object to the current action, you use now, and your object will vanish when the current action is done.
Entries set via now are accessed the same way as standard entries: flash['my-key'].
(see http://api.rubyonrails.org/classes/ActionDispatch/Flash/FlashHash.html#method-i-now)
Try removing the '.now' in your view and instead do
<% if flash[:error] %>

Redirect_to session_path controller and view RAILS DEVISE

Why does this not work? I've tried multiple choices like render and puts, but it doesn't want to change properly. A couple of ideas users?
THE VIEW:
<div id = "container">
<div id = "smaller-container">
<%= user_signed_in? %>
<%= #Uchecker %>
<% else %>
<%= link_to "Sign Up", new_user_registration_path, :id => "SignUpText" %>
</div>
THE CONTROLLER:
class PostsController < ApplicationController
def Uchecker
#Uchecker = redirect_to user_session_path
end
end

Resources