Rails nested resource not updating - ruby-on-rails-4.1

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.

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

Displaying simple search form

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

How to use group_by date with datetime element to display on calendar by day?

I'm using a datetime element on my model but for some reason I can't get it to show up in my calendar. I'm using code in the controller and view to do this, the CSS is irrelevant I think so I wont include that. I'm also using a hash to do it.
Events Controller:
def calendarpage
#events = Event.all
#events_by_date = #events.group_by(&:edate)
#date = params[:date] ? Date.parse(params[:date]) : Date.today
end
CalendarPageView:
<h1>My Calendar</h1>
<div id="events">
<h2 id="month">
<%= link_to "<", date: #date.prev_month %>
<%= #date.strftime("%B %Y") %>
<%= link_to ">", date: #date.next_month %>
</h2>
<%= calendar #date do |date| %>
<%= date.day %>
<% if #events_by_date[date] %><!-- is this even populated?? -->
<ul>
<% #events_by_date[date].each do |event| %>
<li><%= link_to event.title, event%></li> <!-- THIS IS WHAT DOESN'T SHOW -->
<% end %>
</ul>
<% end %>
<% end %>
Here's the relevant database entries:
table: events
id title ... edate
"1" "Test" ... "2014-10-06 20:38:00.000000"
"2" "t2" ... "2014-10-07 20:40:00.000000"
This might also be useful, though I don't think so:
Calendar Helper.rb
module CalendarHelper
def calendar(date = Date.today, &block)
Calendar.new(self, date, block).table
end
class Calendar < Struct.new(:view, :date, :callback)
HEADER = %w[Sunday Monday Tuesday Wednesday Thursday Friday Saturday]
START_DAY = :sunday
delegate :content_tag, to: :view
def table
content_tag :table, class: "calendar" do
header + week_rows
end
end
def header
content_tag :tr do
HEADER.map { |day| content_tag :th, day }.join.html_safe
end
end
def week_rows
weeks.map do |week|
content_tag :tr do
week.map { |day| day_cell(day) }.join.html_safe
end
end.join.html_safe
end
def day_cell(day)
content_tag :td, view.capture(day, &callback), class: day_classes(day)
end
def day_classes(day)
classes = []
classes << "today" if day == Date.today
classes << "notmonth" if day.month != date.month
classes.empty? ? nil : classes.join(" ")
end
def weeks
first = date.beginning_of_month.beginning_of_week(START_DAY)
last = date.end_of_month.end_of_week(START_DAY)
(first..last).to_a.in_groups_of(7)
end
end
end
the calendar displays just fine, and I know that the controller code does get called. But none of the events actually get displayed at all. the 6th and the 7th don't get displayed.
Now, Here's what I'm thinking. I followed a tutorial to make this and I'm thinking that in the tutorial the edate element is a :date element not a :datetime element like I have it, would that make a difference? if so how do I correct for difference in variable type (the extra time info)? if this is the problem do I have to change the Group_by line in the event controller?
One other observation I have is that I appended this code onto the bottom of the view page:
<% #events_by_date["7"].each do |event| %>
<li><%= link_to event.title, event%></li>
<% end %>
and I got an error:
undefined method `each' for nil:NilClass
This may be because I don't understand how Hashtables work, but something is telling me the #events_by_date isn't being populated in the controller :(
what do I do?

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