Edit page not rendered properly - ruby-on-rails

I'm very new to RoR. I'm trying to learn.
This is my user_controller update/edit part.
def edit
binding.break
#user = User.find(params[:id])
end
def update
#user = User.find(params[:id])
#binding.break
if #user.update(params.require(:user).keep_if{|key| #user.attributes[key] != params[:user][key]}.permit(:username, :email, :password))
# Call to debugger
flash[:notice] = "Article was updated successfully."
redirect_to #user
else
#binding.break
flash[:notice] = "Article was not updated successfully."
render 'edit'
end
end
This is my edit.html.erb file
<h1>Edit an existing User</h1>
<% if #user.errors.any? %>
<h2>The following errors prevented the user from being saved</h2>
<ul>
<% #user.errors.full_messages.each do |msg| %>
<%= puts msg%>
<li><%= msg %></li>
<% end %>
</ul>
<% end %>
<%= form_with(model: #user, local: true) do |f| %>
<p>
<%= f.label :username %><br/>
<%= f.text_field :username %>
</p>
<p>
<%= f.label :email %><br/>
<%= f.text_field :email %>
</p>
<p>
<p>
<%= f.label :password %><br/>
<%= f.password_field :password %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
The success case is working fine.
For the negative case where the update fails, I wanted to print the error messages for which the update failed and render it. But currently it just renders the edit page again. Also the #user in the else part of the controller is having the values which is invalid and those are getting filled in the edit page upon rendering. I want to reset to original values and show the errors for which it got failed.
The errors can be anything like, email format not correct or something.
Server logs says
↳ app/controllers/users_controller.rb:19:in `update'
TRANSACTION (0.2ms) rollback transaction
↳ app/controllers/users_controller.rb:19:in `update'
Rendering layout layouts/application.html.erb
Rendering users/edit.html.erb within layouts/application
Username has already been taken
Rendered users/edit.html.erb within layouts/application (Duration: 23.0ms | Allocations: 2337)
Rendered layout layouts/application.html.erb (Duration: 59.2ms | Allocations: 4962)
Completed 200 OK in 152ms (Views: 87.9ms | ActiveRecord: 5.0ms | Allocations: 11120)
Can someone shed some light on this?

render 'edit' with render edit without controller, you need to call #user = User.find(params[:id]) before render to get original value.
If you want to show errors message, grant it to other const and render it in views
def edit
binding.break
#user = User.find(params[:id])
end
def update
#user = User.find(params[:id])
#binding.break
if #user.update(params.require(:user).keep_if{|key| #user.attributes[key] != params[:user][key]}.permit(:username, :email, :password))
# Call to debugger
flash[:notice] = "Article was updated successfully."
redirect_to #user
else
#binding.break
#errors = #user.errors
#user = User.find(params[:id])
flash[:notice] = "Article was not updated successfully."
render 'edit'
end
end
in view, using #errors.full_messages

Related

Ruby on Rails form_with not showing errors, stuck on server side

I'm sure I'm just missing something really simple but I'm pretty stumped. I have a user signup form that's properly identifying errors in the signup process on the server, but it's not passing that information back to the views to render the errors above the form.
controllers/registrations_controller.rb
class RegistrationsController < ApplicationController
def new
#user = User.new
end
def create
#user = User.new(user_params)
if #user.save
redirect_to root_path, notice: "Successfully signed up!"
else
puts 'ERRORS BELOW:'
puts #user.errors.full_messages
render :new
end
end
private
def user_params
params.require(:user).permit(:email, :password, :password_confirmation)
end
end
views/registrations/new.html.erb
<%= form_with model: #user, url: signup_path do |f| %>
<% if #user.errors.any? %>
<div class="alert alert-danger">
<% #user.errors.full_messages.each do |message| %>
<div><%= message %></div>
<% end %>
</div>
<% end %>
<div class='mb-3'>
<%= f.label :email %>
<%= f.text_field :email, class:'form-control', placeholder: 'john#test.com' %>
</div>
<div class='mb-3'>
<%= f.label :password %>
<%= f.password_field :password, class:'form-control', placeholder: 'password' %>
</div>
<div class='mb-3'>
<%= f.label :password_confirmation %>
<%= f.password_field :password_confirmation, class:'form-control', placeholder: 'password' %>
</div>
<div class="mb-3">
<%= f.submit 'Get Started', class: 'btn btn-primary' %>
</div>
<% end %>
routes.rb
Rails.application.routes.draw do
root to:'main#index'
get "signup", to: 'registrations#new'
post "signup", to: 'registrations#create'
get "about-us", to: 'about#index', as: :about
end
View from my console showing the errors getting printed out serverside
Started POST "/signup" for 127.0.0.1 at 2023-01-26 10:18:51 -0600
Processing by RegistrationsController#create as TURBO_STREAM
Parameters: {"authenticity_token"=>"[FILTERED]", "user"=>{"email"=>"asdfasdg", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}, "commit"=>"Get Started"}
ERRORS BELOW:
Password confirmation doesn't match Password
Email Must be a valid email address
Rendering layout layouts/application.html.erb
Rendering registrations/new.html.erb within layouts/application
Rendered registrations/new.html.erb within layouts/application (Duration: 3.8ms | Allocations: 2734)
Rendered shared/_navbar.html.erb (Duration: 0.2ms | Allocations: 134)
Rendered shared/_flash.html.erb (Duration: 0.1ms | Allocations: 33)
Rendered layout layouts/application.html.erb (Duration: 54.5ms | Allocations: 17541)
Completed 200 OK in 423ms (Views: 56.7ms | ActiveRecord: 1.1ms | Allocations: 22605)
I've tried passing them in as a flash notice, as well as not even rendering :new after #user.save fails, not sure what else to try. A lot of solutions to similar problems I've found on here seem to have been solved by putting the if/else block in the create function, but I already have that in. Not sure what I'm missing.
I should also add that I am able to create a User when I enter in a proper email and matching passwords, and it does not create a user when I fail those two checks, it just doesn't pass those errors back to the client
Processing by RegistrationsController#create as TURBO_STREAM
Probably that's the problem, but you can disable turbo
Just add data-turbo="false" attribute to this form
<%= form_with model: #user, url: signup_path, data: { turbo: false } do |f| %>
In this case it will be usual HTTP request

Rails Form not rendering json response

I am fairly new to rails, so please bear with me. I have a very simple form that takes a couple values and sends it to my EmailController. I run very basic logic on it and just want to return the JSON to the view. It looks like the controller action is properly rendering the data (I can see in the server output), but the view doesn't change at all.
Here is my home.html.erb
<%= form_with(url: '/api/v1/emails', method: 'post') do |f| %>
<%= f.fields_for :email do |ev| %>
<%= ev.label :address %>
<%= ev.text_field :address %>
<% end %>
<%= f.submit 'Verify' %>
<% end %>
and emails_controller.rb (simplified)
class Api::V1::EmailController < Api::V1::BaseController
def create
#email = Email.new(email_params)
if #email.save
redirect_to api_v1_email_path(#email.id)
else
render json: #email.errors, status: :unprocessable_entity
end
end
def show
if #email
render 'show'
else
render json: #email, status: :not_found
end
end
def email_params
params.require(:email).permit(:address, :id)
end
It says it renders the template, but the view doesn't change:
Rendering api/v1/email/show.html.erb within layouts/application
Rendered api/v1/email/show.html.erb within layouts/application (0.9ms)
Completed 200 OK in 611ms (Views: 593.6ms | ActiveRecord: 1.3ms)
The template is just simple "hello world" plain text
Thank you in advance for the help!
I ended up having to create the form with local: true and it resolved the issue.
<%= form_with(url: '/api/v1/emails', method: 'post', local: true) do |f| %>

No template found for UsersController#create, rendering head :no_content

OK, previously I had a problem with a no template error from users#create, now it complete 200 OK however does not redirect at all. Below is my edited users_controller.rb
I have a Signup, Login, Logout rails application with users as a resource. I am trying to save the first user in the database so I can then login but this error is server output when I try to "users#new" and "users#create" the full error is below, then my users_controller.rb and views/users -> new.html.erb
No template found for UsersController#create, rendering head :no_content
Completed 204 No Content in 35ms (ActiveRecord: 0.5ms)
users_controller.rb
def new
#user = User.new
end
def create
#user = User.new(user_params)
if (#user = User.find_by_email(params[:email]))
flash[:success] = "User already exists."
if #user.save
session[:user_id] = user.id
flash[:success] = "New User created."
redirect_to '/layouts/application'
else
render 'new'
end
end
end
new.html.erb
<h1>Sign Up</h1>
<%= form_with(model: #user) do |f| %>
<p> Username:</br> <%= f.text_field :username %> </p>
<p> Email:</br> <%= f.text_field :email %> </p>
<p> Password:</br> <%= f.password_field :password%></p>
<%= f.submit "Signup" %>
<% end %>
<% if #user.errors.any? %>
<ul class="Signup_Errors">
<% for message_error in #user.errors.full_messages %>
<li>* <%= message_error %></li>
<% end %>
</ul>
<% end %>
</div>
Do I have to have another html.erb file? And how can I tell what that has to be? Sorry for the obvious question, newb here.
As per your code if the User is not present it will not enter in the if block. Rails end up trying to find create.html as the current action is create.
To avoid this you must redirect it somewhere or render a template which you have done in the next if and else but it's not executing.
The condition is not letting it redirect to anywhere. Try moving the if block out like this.
def create
#user = User.new(user_params)
if User.exists?(email: params[:email]) # I think this should be `user_params[:email]` instead of `params[:email]`
flash[:error] = "User already exists."
redirect_to 'whereever/you/want/to/redirect' and return
end
if #user.save
session[:user_id] = user.id
flash[:success] = "New User created."
redirect_to '/layouts/application'
else
render 'new'
end
end

My Ruby on Rails won't post new messages or edit messages

I'm creating a reddit clone where users can post messages and edit them after posting them. I have the views set up to access the posts and to even make a new post, but when I try to edit a post as an administrator or make a new post as a member, the app flashes an error, saying that the topic is blank.
I'm trying to add user avatars to each post, but I'd like to settle this bug before I move forward. I'm not sure what piece of code is responsible for this, but I've narrowed it down to a few culprits.
It could be the render line here:
<h1>Edit Post</h1>
<div class="row">
<div class="col-md-4">
<p>Guidelines for posts</p>
<ul>
<li>Make sure it rhymes.</li>
<li>Use complete sentences.</li>
<li>Post messages with more than 30 characters.</li>
</ul>
</div>
<div class="col-md-8">
<%= render partial: 'form', locals: { topic: #topic, post: #post } %>
</div>
</div>
Here another file that also has this render partial.
<h1>New Post</h1>
<div class="row">
<div class="col-md-4">
<p>Guidelines for posts</p>
<ul>
<li>Make sure it rhymes.</li>
<li>Use complete sentences.</li>
<li>Post messages with more than 30 characters.</li>
</ul>
</div>
<div class="col-md-8">
<%= render partial: 'form', locals: { topic: #topic, post: #post } %>
</div>
</div>
Lastly is render partial:
<%= form_for [topic, post] do |f| %> <!-- It's kind of like a module! -->
<% if post.errors.any? %>
<div class="alert alert-danger"
<h4>There are <%= pluralize(post.errors.count, "error") %>.</h4>
<ul>
<% post.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<%= form_group_tag(post.errors[:title]) do %>
<%= f.label :title %>
<%= f.text_field :title, class: 'form_control', placeholder: "Enter post title" %>
<% end %>
<%= form_group_tag(post.errors[:body]) do %>
<%= f.label :body %>
<%= f.text_area :body, rows: 8, class: 'form-control', placeholder: "Enter post body" %>
<% end %>
<div class="form-group">
<%= f.submit "Save", class: 'btn btn-success' %>
</div>
<% end %>
What do you think? I'm new to Ruby, and partials are cool, but it's still a new concept. And if this the source of the error, How can I fix it?
EDIT: It was noted that I could be my routes, so here is my routes file.
Rails.application.routes.draw do
devise_for :users
resources :users, only: [:update]
resources :topics do
resources :posts, except: [:index]
end
get 'about' => 'welcome#about'
root to: 'welcome#index'
end
Here's the post_controller also:
class PostsController < ApplicationController # using private methods to Refactor code!
def show
#topic = Topic.find(params[:topic_id])
#post = Post.find(params[:id])
end
def new
#topic = Topic.find(params[:topic_id])
#post = Post.new
authorize #post # from include Pundit in the application controller, authorize is an inherited method
end
def create
#topic = Topic.find(params[:topic_id])
#post = current_user.posts.build(post_params)
authorize #post
if #post.save
flash[:notice] = "Post was saved."
redirect_to [#topic, #post]
else
flash[:error] = "There was an error saving the post. Please try again."
render :new
end
end
def edit
#topic = Topic.find(params[:topic_id])
#post = Post.find(params[:id])
authorize #post
end
def update
#topic = Topic.find(params[:topic_id])
#post = Post.find(params[:id])
authorize #post
if #post.update_attributes(post_params)
flash[:notice] = "Post was updated."
redirect_to [#topic, #post]
else
flash[:error] = "There was an error saving the post. Please try again."
render :edit
end
end
private
def post_params
params.require(:post).permit(:title, :body)
end
end
EDIT:
It was noted that the topic_id could be seen as nil, so I looked at the activity log displayed on my terminal.
Started POST "/topics/1/posts" for 127.0.0.1 at 2014-12-12 14:14:46 +0300
Processing by PostsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"glyWpWi1oJpZFuP2g0FvYowq1NG8edZEYzzirnX9pRE=", "post"=>{"title"=>"Hello sdfsd", "body"=>"fdsfsfsd dfdfsdfsfs dsfsdfsfdsfs"}, "commit"=>"Save", "topic_id"=>"1"}
Topic Load (0.1ms) SELECT "topics".* FROM "topics" WHERE "topics"."id" = ? LIMIT 1 [["id", 1]]
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = 8 ORDER BY "users"."id" ASC LIMIT 1
(0.0ms) begin transaction
(0.0ms) rollback transaction
Rendered posts/_form.html.erb (1.4ms)
Rendered posts/new.html.erb within layouts/application (1.8ms)
Completed 200 OK in 73ms (Views: 69.5ms | ActiveRecord: 0.2ms)
Does this mean that the my app recognized the post's topic ID as 1?
Add #post.topic = #topic to your controller after #post is build (to create and update):
...
#post = current_user.posts.build(post_params)
#post.topic = #topic
...

Rails - New & edit not working with form_for

I'm working through this Epicodus lesson and I just refactored my form partial for the new and edit views, but the new & edit actions are not working. When submitting the update, I'm getting the "name can't be blank" error.
Here's my new, create, edit & update actions in my contacts_controller:
def new
#contact = Contact.new
end
def create
#contact = Contact.new name: params[:name],
email: params[:email],
phone: params[:phone]
if #contact.save
flash[:notice] = "#{#contact.name} added."
redirect_to contacts_path
else
render 'new'
end
end
def edit
#contact = Contact.find(params[:id])
end
def update
#contact = Contact.find(params[:id])
if #contact.update name: params[:name],
email: params[:email],
phone: params[:phone]
flash[:notice] = 'Contact updated.'
redirect_to contact_path(#contact)
else
render 'edit'
end
end
My edit view:
<% content_for(:title, "Edit #{#contact.name} | Wikipages") %>
<h1>Edit <%= #contact.name %></h1>
<%= render 'errors'%>
<%= render 'form'%>
<p><%= link_to 'Return to contacts', '/contacts' %></p>
My new view:
<% content_for(:title, "New contact | Wikipages") %>
<h1>New contact</h1>
<%= render 'errors'%>
<%= render 'form'%>
<p><%= link_to 'Return to contacts', '/contacts', class: 'btn btn-default' %></p>
My form partial:
<%= form_for(#contact) do |f| %>
<div class="form-group">
<%= f.label :name %>
<%= f.text_field :name %>
</div>
<div class="form-group">
<%= f.label :phone %>
<%= f.text_field :phone %>
</div>
<div class="form-group">
<%= f.label :email %>
<%= f.text_field :email %>
</div>
<%= f.submit(class: "btn btn-primary")%>
<% end %>
And my routes:
Rails.application.routes.draw do
root 'contacts#index'
resources :contacts do
resources :phones
end
end
Here's the output from my log for the new:
Started POST "/contacts" for 127.0.0.1 at 2014-09-23 07:00:34 -0400
Processing by ContactsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"q59xzpBWXEs58qStmPcnpEqm89finUQKiUvYsjRYm8Q=", "contact"=>{"name"=>"Lance", "phone"=>"", "email"=>""}, "commit"=>"Create Contact"}
(2.1ms) BEGIN
(0.2ms) ROLLBACK
Rendered contacts/_errors.html.erb (0.6ms)
Rendered contacts/_form.html.erb (3.2ms)
Rendered contacts/new.html.erb within layouts/application (6.0ms)
Completed 200 OK in 214ms (Views: 207.5ms | ActiveRecord: 2.3ms)
Here's the output from my log for the edit:
Started PATCH "/contacts/12" for 127.0.0.1 at 2014-09-23 06:48:02 -0400
Processing by ContactsController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"q59xzpBWXEs58qStmPcnpEqm89finUQKiUvYsjRYm8Q=", "contact"=>{"name"=>"Chuck Wight", "phone"=>"435345345e", "email"=>"desfwrf#er.com"}, "commit"=>"Update Contact", "id"=>"12"}
Contact Load (0.3ms) SELECT "contacts".* FROM "contacts" WHERE "contacts"."id" = $1 LIMIT 1 [["id", 12]]
(0.1ms) BEGIN
(0.4ms) ROLLBACK
Rendered contacts/_errors.html.erb (0.5ms)
Rendered contacts/_form.html.erb (4.4ms)
Rendered contacts/edit.html.erb within layouts/application (7.2ms)
Completed 200 OK in 208ms (Views: 201.0ms | ActiveRecord: 0.8ms)
Any thoughts?
Your params nested under contact and you are passing params to your create and update action directly. So try paarams[:contact][:email] instead of params[:email]
Like this :
def create
#contact = Contact.new name: params[:contact][:name],
email: params[:contact][:email],
phone: params[:contact][:phone]
if #contact.save
flash[:notice] = "#{#contact.name} added."
redirect_to contacts_path
else
render 'new'
end
end
def update
#contact = Contact.find(params[:id])
if #contact.update name: params[:contact][:name],
email: params[:contact][:email],
phone: params[:contact][:phone]
flash[:notice] = 'Contact updated.'
redirect_to contact_path(#contact)
else
render 'edit'
end
end
Clearly in your update action your are getting #contact as nil. So try make changes I suggested in your controller action. Hope this help you.

Resources