Rails - New & edit not working with form_for - ruby-on-rails

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.

Related

Edit page not rendered properly

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

Rails commits change from form, but nothing written to DB

I think there must be something simple that I'm not setting up correctly, but I cannot figure out this behavior. The user submits and edit form, rails log shows the change is committed, but when I load the record again, it's still the same.
Here's the form
<%= form_for(#deal) do |f| %>
<div class="deal-<%= #deal.id %>">
<div class="field">
<%= f.label :headline %><br />
<%= f.text_field :headline, required: true %>
</div>
<div class="field">
<%= f.label :matter %>
<%= f.text_field :matter %>
</div>
<div class="field">
<%= f.label :summary %>
<%= f.text_area :summary %>
</div>
<%= f.submit "Update" %>
</div>
<% end %>
and relevant parts of controller
def edit
#deal = Deal.find(params[:id])
end
def update
#deal = Deal.find(params[:id])
if #deal.save
flash[:success] = 'Your deal was updated'
redirect_to root_path
else
render 'edit'
end
end
And the output on submit
Started PATCH "/deals/1" for ::1 at 2017-03-21 13:15:17 +0100
Processing by DealsController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"Rctg6qcVMfOutyXjZihiR5+zhagr+cduNfA6TSYqOHmjvh+dcQl9TZ/MxZbY+IMyt0LU2PQrsyCjcUJczGcTKg==", "deal"=>{"headline"=>"testheadline", "matter"=>"matter", "summary"=>"First test summary"}, "commit"=>"Update", "id"=>"1"}
Deal Load (0.1ms) SELECT "deals".* FROM "deals" WHERE "deals"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
(0.0ms) begin transaction
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 6], ["LIMIT", 1]]
(0.1ms) commit transaction
Redirected to http://localhost:3000/
Completed 302 Found in 5ms (ActiveRecord: 0.4ms)
def update
#deal = Deal.find(params[:id])
if #deal.update(deal_params)
flash[:success] = 'Your deal was updated'
redirect_to root_path
else
render 'edit'
end
end
private
def deal_params
params.require(:deal).permit(:headline, :matter, :summary)
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 4 - partial rendered with update.js.erb not showing updated values

On the account settings page for my Rails app I am trying to use Ajax to have the displayed users settings info updated after the update form is submitted. Right now when I submit the form the database gets updated and the _account_settings.html.erb partial appears to get re-rendered, but the partial doesn't show the updated information. For example, say the users name is "John Doe" and he clicks the '#edit_name' link. This renders the _name_form.html.erb which he can use to change his name. When he changes his name and submits the form, let's say he changes it to "Joe Blow", the form disappears and the 'Name: <%= current_user.name %> - click to edit' shows up again but the name is still "John Doe" even though the name in the DB is now "Joe Blow". If I refresh the page the name now appears as "Joe Blow". I am using devise and made a custom registrations controller to allow the user to update certain attributes without entering a password (name still requires the current password). I used this code provided by the devise and simply added
respond_to do |format|
format.html { redirect_to edit_user_registration_path }
format.js
end
to the end of the 'if #user.update_attributes(account_update_params)' block in the above link. Any ideas as to why the re-rendered partial isn't showing the updated user information?
edit.html.erb
<h1>Account Settings</h1>
<div id="account_settings_container">
<%= render 'account_settings' %>
</div>
_account_settings.html.erb
<div class="user-attribute-container">
<%= link_to "#", class: "edit-attribute", id: "edit_name", remote: true do %>
<p>Name: <%= current_user.name %> - click to edit</p>
<% end %>
</div>
<div class="user-attribute-container">
<%= link_to "#", class: "edit-attribute", id: "edit_email", remote: true do %>
<p>Email: <%= current_user.email %> - click to edit</p>
<% end %>
</div>
<div class="user-attribute-container">
<%= link_to "#", class: "edit-attribute", id: "edit_password", remote: true do %>
<p>Password: click to edit your password</p>
<% end %>
</div>
<%= javascript_tag do %>
$("#edit_name").click(function() {
$(this).hide().after("<%= escape_javascript(render('name_form')) %>");
});
$("#edit_email").click(function() {
$(this).hide().after("<%= escape_javascript(render('email_form')) %>");
});
$("#edit_password").click(function() {
$(this).hide().after("<%= escape_javascript(render('password_form')) %>");
});
<% end %>
_name_form.html.erb (the email and password form partials have :email, :password & :password_confirmation instead of :name, otherwise they're the same)
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name), :method => :put, :html => { id: "edit_user_name" }, remote: true) do |f| %>
<%= f.label :name, "Name" %>
<%= f.text_field :name %>
<%= f.label :password_field, "Password" %>
<%= f.password_field :current_password %>
<%= f.submit "Update" %>
<% end %>
update.js.erb
$("#account_settings_container").html("<%= escape_javascript(render('account_settings')) %>");
From the log file:
Started PUT "/users" for 127.0.0.1 at 2014-06-09 15:01:21 -0700<br>
Processing by RegistrationsController#update as JS<br>
Parameters: {"utf8"=>"✓", "user"=>{"name"=>"Joe Blow", "current_password"=>"[FILTERED]"}, "commit"=>"Update"}<br>
[1m[36mUser Load (0.0ms)[0m [1mSELECT "users".* FROM "users" WHERE "users"."id" = 14 ORDER BY "users"."id" ASC LIMIT 1[0m<br>
[1m[35mUser Load (0.0ms)[0m SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 14]]<br>
[1m[36m (0.0ms)[0m [1mBEGIN[0m<br>
[1m[35mSQL (0.0ms)[0m UPDATE "users" SET "name" = $1, "updated_at" = $2 WHERE "users"."id" = 14 [["name", "Joe Blow"], ["updated_at", Mon, 09 Jun 2014 15:01:21 PDT -07:00]]<br>
[1m[36m (0.0ms)[0m [1mCOMMIT[0m<br>
Rendered registrations/_name_form.html.erb (15.6ms)<br>
Rendered registrations/_email_form.html.erb (0.0ms)<br>
Rendered registrations/_password_form.html.erb (15.6ms)<br>
Rendered registrations/_account_settings.html.erb (46.9ms)<br>
Rendered registrations/update.js.erb (46.9ms)<br>
Completed 200 OK in 219ms (Views: 78.1ms | ActiveRecord: 0.0ms)
Custom devise registrations controller:
class RegistrationsController < Devise::RegistrationsController
def update
#user = User.find(current_user.id)
successfully_updated = if needs_password?(#user, params)
#user.update_with_password(devise_parameter_sanitizer.sanitize(:account_update))
else
# remove the virtual current_password attribute
# update_without_password doesn't know how to ignore it
params[:user].delete(:current_password)
#user.update_without_password(devise_parameter_sanitizer.sanitize(:account_update))
end
if successfully_updated
# sign_in #user, :bypass => true
respond_to do |format|
format.html { redirect_to edit_user_registration_path }
format.js
end
else
respond_to do |format|
format.html { render "edit" }
format.js
end
end
end
private
def needs_password?(user, params)
user.email != params[:user][:email] || params[:user][:password].present? || user.name != params[:user][:name]
end
end
current_user is generated by Devise using a before_filter. So the object returned, will be the user as it was before that action method was called. You need to use the #user object which is the user object that is modified by the action method.
So for example:
<p>Name: <%= #user.name %> - click to edit</p>

Can't get AJAX form partial working on Rails 3.2

I'm trying to render a form with AJAX. The non-ajax version works fine, but the ajaxified version doesn't. The link to it is in the index.html.erb. The Webrick server shows:
Started GET "/categories/3/new_sub" for 127.0.0.1 at 2012-11-19 17:19:27 -0500
Processing by CategoriesController#new_sub as JS
Parameters: {"id"=>"3"}
Category Load (0.1ms) SELECT "categories".* FROM "categories" WHERE "categories"."id" = ? LIMIT 1 [["id", "3"]]
Rendered categories/_form.html.erb (1.8ms)
Rendered categories/new_sub.js.erb (3.6ms)
Completed 200 OK in 8ms (Views: 6.3ms | ActiveRecord: 0.1ms)
Here's my Category controller:
# GET /categories
# GET /categories.json
def index
#categories = Category.roots
respond_to do |format|
format.html # index.html.erb
format.json { render json: #categories }
end
end
# GET /categories/1/new_sub.html
# GET /categories/1/new_sub.js
def new_sub
#parent = Category.find(params[:id])
#category = Category.new
respond_to do |format|
format.html
format.js
end
end
index.html.erb:
<h1>Listing categories</h1>
<%= recurse_categories(#categories) %>
<br />
<%= link_to 'New Category', new_category_path %>
recurse_categories helper:
def recurse_categories(cats)
s = "<ul>"
cats.each do |cat|
s << "<li id=\"#{cat.id}\">#{link_to cat.name, new_sub_category_path(cat), remote: true}</li>"
if cat.has_children?
s << recurse_categories(cat.children)
end
end
s << "</ul>"
s.html_safe
end
new_sub.js.erb:
$('ul').after(<%= render partial: "form", locals: { parent: #parent, category: #category } %>);
_form.html.erb:
<%= form_for(category) do |f| %>
<div class="field">
<%= f.text_field :name %>
<%= f.hidden_field :ancestry, value: "#{parent.ancestry + '/' + parent.id.to_s}" %>
<%= f.submit "Create subcategory" %>
</div>
<% end %>
Your "ul" tag is under category error's condition block. Are you sure you want to append your response in "error_explanation" div.
You can have an span tag and use it in new_sub.js.erb
<div class="field">
<span id="subcat"/>
<%= f.text_field :name %>
<%= f.hidden_field :ancestry, value: "#{parent.ancestry + '/' + parent.id.to_s}" %>
<%= f.submit "Create subcategory" %>
Fixed it! I just forgot quotation marks around the jquery selector and parameter, DUH!

Resources