Ruby on rails changes not reflecting after editing user's details - ruby-on-rails

I am Rails newbie. I am creating a section that is pulling existing user's details and when the user click on edit, he can save the changes he has made. However, the changes aren't reflecting once the user saves it. Can you tell me what I am missing in here?
Here's the html/ruby form I am using:
<%= form_tag(html: {:id => 'user_profile_form'}, :url => patient_profile_path(#user), :method => :put) do %>
<%= text_field_tag(:inputFieldName, "#{#user.first_name} #{#user.last_name}", {:disabled => true}) %>
<%= submit_tag 'Save', :id=> 'saveButton' %>
<%= end %>
Here's the routes:
put :patient_profile, to: 'users#patient_profile'
post :dashboard, to: 'dashboard#index'
Here are the controller codes:
def patient_profile
if params[:user]
u = params[:user]
#user.first_name = u[:first_name] unless u[:first_name].nil? || u[:first_name].empty?
#user.last_name = u[:last_name] unless u[:last_name].nil? || u[:last_name].empty?
#user.save!
# index
render :index
end
end

It doesn't look like your form is actually updating anything since your form fields don't match your model. Try simplifying your form action:
View
<%= form_for(#user, html: {:id => 'user_profile_form'}, :url => patient_profile_path(#user), :method => :put) do |f| %>
<%= f.text_field :first_name %>
<%= f.text_field :last_name %>
<%= f.submit "Update User" %>
<%= end %>
Controller:
def patient_profile
# TODO: Handle failed validation
#user.update_attributes!(params[:user])
# index
render :index
end
end
def user_params
params.require(:user).permit(:first_name, :last_name)
end

Related

Rails double the records on update_attributes

My update function double the records for nested items in model on submit.
The one, which is NOT in the fields_for works as expecting, but every record in fields_for is doubling.
What am I missing? Any help will be highly appreciated
def edit
#printer = Printer.find(params[:id])
end
def update
#printer = Printer.find(params[:id])
if #printer.update_attributes(printer_params)
redirect_to #printer
else
render 'edit'
end
end
def printer_params
params.require(:printer).permit(:model, colors_attributes: [:color], materials_attributes: [:material], printer_photos_attributes: [:image_url] )
end
edit.html.erb
<%= form_for #printer, html: { multipart: true }, :url => url_for(:controller => 'printers', :action => 'update') do |p|%>
<%= p.text_field :model %>
<%= p.fields_for :colors do |color|%>
<%= color.text_field :color %>
<% end %>
<%= p.submit "Edit" %>
<% end %>
You are missing :id in printer_params. Without :id each your update for nested params is considered to be a new record. It should be as following for your colors_attributes:
def printer_params
params.require(:printer).permit(:model, colors_attributes: [:id, :color], materials_attributes: [:material], printer_photos_attributes: [:image_url] )
end
I guess, you should also correct your other nested attributes in this method.

Connecting routes, views and controllers (Rails)

I'm learning Rails so please pardon my amateur mistakes, but I've been stuck for about an hour or two and have made negative progress.
Goal:
From the user profile view, link to a form that allows this user
to change their email. Once the form is submitted, it should trigger
an appropriate method within the user controller.
I can handle the rest, I just haven't managed to connect the parts mentioned above. I have been reading railsTutorial.org and guides.rubyonrails.org but haven't been able to understand routing form_for() sufficiently.
User Profile Link:
<%= #user.email %> <%= link_to "(change)", email_path(#user) %>
Routes
Rails.application.routes.draw do
get 'email' => 'users#email_form'
post 'email' => 'users#changeemail'
end
User Controller
class UsersController < ApplicationController
def email_form
#user = User.find(params[:id])
end
def changeemail
#user = User.find(params[:id])
redirect_to #user
end
end
Currently the error I get once I click the link is Couldn't find User with 'id'= which I assume means user ID is nil because I fail at passing it.
I would greatly appreciate an explanation of what data is being passed through this workflow so I can be a better developer, thank you very much!
EDIT:
The form itself:
<%= form_for(#user, url: user_path(#user)) do |f| %>
<%= render 'shared/error_messages' %>
<%= f.label :new_email %>
<%= f.text_field :new_email, class: 'form-control' %>
<%= f.label :password %>
<%= f.password_field :password, class: 'form-control' %>
<%= f.submit "Submit New Email", class: "btn btn-primary" %>
<% end %>
You could do this (note :id and "as"):
Rails.application.routes.draw do
get 'email/:id' => 'users#email_form', as :email
post 'email/:id' => 'users#changeemail', as :change_email
end
The :id is then expected to be part of the route.
Alternatively, pass the id directly when generating the url:
<%= #user.email %> <%= link_to "(change)", email_path(id: #user) %>
This will make a call to "UsersController#update"
<%= form_for(#user, url: user_path(#user)) do |f| %>
...instead you would use something like::
<%= form_for(#user, url: change_email_path(#user), method: :put) do |f| %>
http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-form_for
...but in terms of best practices, if you want to do separate flow for email updating, you could be more explicit in treating it as a different resource (even though it's still the user record).
For example, you could map these to an explicit 'resource' with a #show and #update action...
Routes:
resources :user_emails, only: [:show, :update]
Controller:
class UserEmailsController < ApplicationController
def show
#user = User.find(params[:id])
end
def update
#user = User.find(params[:id])
redirect_to #user # goes back to UsersController#show
end
end
Then the route would be:
<%= #user.email %> <%= link_to "(change)", user_email_path(#user) %>
In this case we don't have to say (id: #user) since the 'resource' generates the right urls for you.
...and this would be
<%= form_for(#user, url: user_email_path(#user), method: :post) do |f| %>

Database querying through Http in rails?

I am working on rails app , In which I have created a table Product Name:string and Number: integer.
The application should give user a form where he can search a product by his number if product exists it should give product name from database.
My search.html.erb is this.
<%= form_for #products, :url => { :action => "create" }, :html => {:class => "nifty_form"} do |f| %>
<%= f.text_area :number, :size => "60x12" %>
<%= f.submit "Search" %>
<% end
What will be the definition of search Method in ProductController and routes i need to add in routes.rb?
Irrespective of nifty forms, this is how I would have done this:
In config/routes.rb
replace resources :products' with
resources :products do
post 'search', :on => :collection
end
This will give me a search_products_path
In your view:
<%= form_for(:search, :url => search_products_path) do |f| %>
<%= f.text_field :number, :placeholder => "Enter number to search" %>
<%= f.submit "Search" %>
<% end %>
In your products_controller.rb
def search
number = params[:search][:number]
#result = Product.find_by_number(number)
#not_found = true unless #result
end
In your views/products/search.html.erb, use #result to show the product information; take care while checking whether or not the desired product is actually found or not. I have set the boolean #not_found in case it doesn't exist.

Why am I unable to save an associated object in a has_one relationship?

I've got a pickem object that has one result. I'm having an issue getting the result to save properly to the database.
pickems_controller.rb
def results
#pickem = Pickem.find params[:id]
# #pickem.result = #pickem.build_result if #pickem.result.blank?
#pickem.result = Result.new
end
def update_results
#pickem = Pickem.find params[:id]
#pickem.result = Result.new params[:pickem][:result_attributes]
if #pickem.result.update_attributes params[:pickem][:result_attributes]
redirect_to edit_pickem_results_path(#pickem), :notice => 'The results have been successfully updated.'
else
render "edit"
end
end
results.html.erb
<%= simple_form_for #pickem, :url => edit_pickem_results_path(#pickem), :method => :put, do |f| %>
<%= f.simple_fields_for :result do |r| %>
<%= r.input :first_name %>
...
<% end %>
<%= f.submit :class => 'btn btn-success', :label => 'Submit Results' %>
<% end %>
pickem.rb
has_one :result, :dependent => :destroy
accepts_nested_attributes_for :result
result.rb
belongs_to :pickem
I was initially using the build_result code that is commented out in the controller but had to back out of that. With build_result a result record was saved to the database the instant somebody clicked into the results form. There are rules in place in the application that don't allow users to make any picks if a result has been entered. So even if a user clicked into the result form but didn't submit, the result was still being created.
How can I build my form and save the result record only when the user clicks save, and not when the form is loaded? The current solution I've pasted above does not work. It saves a result record with the appropriate foreign key but never gets the form data. If I dump #pickem.result the correct form data is in the result object, I just can't get it to save right. Other solutions I've tried save the form data correctly but have a foreign key of 0.
EDIT:
For whatever reason #pickem.result = Result.new was still saving a record to the database so I changed it to #result = Result.new and updated the form as follows:
<%= simple_form_for #result, :url => edit_pickem_results_path(#pickem), :method => :put, do |r| %>
<%= r.input :first_name %>
<%= r.submit :class => 'btn btn-success', :label => 'Submit Results' %>
<% end %>
Then using the suggestion from Chuck W of #result = #pickem.result.build params[:result], I get undefined methodbuild' for nil:NilClass`.
pickems_controller.rb
def results
#pickem = Pickem.find params[:id]
#pickem.result.blank? ? #result = Result.new : #result = #pickem.result
end
def update_results
#pickem = Pickem.find params[:id]
 #result = #pickem.result.build params[:pickem][:result]
if #result.save
redirect_to edit_pickem_results_path(#pickem), :notice => 'The results have been successfully updated.'
else
render "edit"
end
end
Then, your view should look something like this:
<%= simple_form_for #pickem, :url => edit_pickem_results_path(#pickem), :method => :put, do |f| %>
<%= f.simple_fields_for #result do |r| %>
<%= r.input :first_name %>
...
<% end %>
<%= f.submit :class => 'btn btn-success', :label => 'Submit Results' %>
<% end %>
You might have to play around with how the parameters are being passed back to the update_results action (I'm pretty new to rails), but I think you get the gist of it.

ActionController::MethodNotAllowed (Only get and post requests are allowed.):

Not sure what's going on. I've used the following bit of code to try and edit the name of a category, but I'm getting the error message above. My code for the form and submit for the edit is: -
<% form_for :category, :url => categories_url(#category),:html => { :method => :put } do |f| -%>
<p>Name: <br /><%= f.text_field :name, :size => 60 %></p>
<%= submit_tag 'Save' %> or <%= link_to 'cancel', admin_categories_url%>
So pretty straight forward stuff. My controller code is: -
def edit
#category = Category.find(params[:id])
end
# PUT /categories/1
# PUT /categories/1.xml
def update
#category = Category.find(params[:id])
#category.update_attributes(params[:category])
respond_to do |wants|
wants.html { redirect_to admin_categories_url }
wants.xml { render :xml => #category.to_xm }
end
end
This code has worked for other things - such as blog articles, so I'm not sure where I{"m going wrong. Help??
I think you want :url => category_url(#category) (non-plural).
This tends to be a bit cleaner... Let the Routing system figure out how best to save the #category.
/app/controllers/admin_categories_controller.rb (guessed at this)
def new
#category = Category.new
end
/app/views/admin_categories/new.html.erb
<% form_for #category do |f| %>
<p>
<%= f.label :name%>: <%= f.text_field :name, :size=>60%>
</p>
<%= f.submit :save%> or <%= link_to 'cancel', admin_categories_url%>

Resources