Rails 4 - save / update nested record - ruby-on-rails

I have user and user has one address. I need to create a form which is like edit profile page. Which will save few user's fields and save user's address. But everytime while I submit form, user's data is correctly being saved in DB, but for address, new record is being created every time with correct user_id value and other field value is null.
Query: How to save address in database?
class User < ActiveRecord::Base
has_one :address
accepts_nested_attributes_for :address
end
class Address < ActiveRecord::Base
belongs_to :user
belongs_to :country
attr_accessor :city, :zip_code, :street_address, :state
end
Form
<%= form_for #user, url: {controller: :profiles, action: :update} do |f| %>
<%= f.text_field :first_name, autofocus: true, :placeholder => 'First Name' %>
<%= f.text_field :last_name, :placeholder => 'Last Name' %>
<%= f.fields_for :address do |address_fields| %>
<%= address_fields.select :country_id, options_for_select(["Select One", "Cell", "Work", "Office", "Home", "Other"],:disabled => ["Select One"]) %>
<%= address_fields.select :state, options_for_select(["Select One", "Cell", "Work", "Office", "Home", "Other"],:disabled => ["Select One"]) %>
<%= address_fields.text_field :city, :placeholder => 'City' %>
<%= address_fields.text_area :street_address, :placeholder => 'Street Address' %>
<%= address_fields.text_field :zip_code, :placeholder => 'Zip Code' %>
<% end %>
<%= f.submit "Update", :class => 'btn btn-primary' %>
controller
class ProfilesController < ApplicationController
def edit
#user = current_user
#user.build_address if #user.address.nil?
end
def update
#user = current_user
respond_to do |format|
if #user.update(user_params)
format.html { redirect_to welcome_url, notice: 'Your Profile was successfully updated.' }
format.json { render :show, status: :ok, location: #user }
else
format.html { render :edit }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
private
def set_user
#user = User.find(params[:id])
end
def user_params
params.require(:user).permit(:first_name, :last_name, :email, :phone_number, :date_of_birth, address_attributes: [ :id, :city, :country_id, :zip_code, :street_address, :state])
end
end

Your country_id select field will return a string, while your Address model probably expects an integer. This might prevent the record from being saved correctly?

Related

Nested Forms in Rails 4.0.3

Im struggling with a nested form in Rails 4, this is the first time that I made a form of that kind. I have read lots of documentation but Im not able to make it work. :-(
I have two models: Person and Disease. One person can have many diseases and one disease belongs to person. Looks quite simple. The form for Diseases is not saved in the database.
Person Model:
class Person < ActiveRecord::Base
belongs_to :user
has_many :diseases, :dependent => :destroy #if you delete a person you also delete all diseases related
has_many :appointments, :dependent => :destroy
validates_presence_of :name, :email
validates :name, :length => {:maximum => 50, :too_long => "name is too long"}
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
validates :email, format: { :with => VALID_EMAIL_REGEX , message: "is invalid" }
accepts_nested_attributes_for :diseases
end
Disease Model:
class Disease < ActiveRecord::Base
belongs_to :person
has_many :treatments
validates_presence_of :name, :start
validates :name, :length => {:maximum => 50, :too_long => "is too long, you can use the description field"}
validate :start_must_be_before_end, :unless => [:chronical, :unfinished], :presence => true
validates :end, :presence => true, :unless => [:chronical, :unfinished], :presence => true
validates :description, :length => {:maximum => 5000, :too_long => "is too long"}
def start_must_be_before_end
if self[:end] < self[:start]
errors.add(:start, "must be before end time")
return false
else
return true
end
end
end
People Controller:
def create
current_user
#person = Person.new(person_params)
#person.user_id = #current_user.id
respond_to do |format|
if #person.save
format.html { redirect_to #person, notice: 'Person was successfully created.' }
format.json { render action: 'show', status: :created, location: #person }
else
format.html { render action: 'new' }
format.json { render json: #person.errors, status: :unprocessable_entity }
end
end
end
def person_params
params.require(:person).permit(:name, :surname, :gender, :birthdate, :bloodtype, :user_id, :phone, :email, diseases_attributes: [:id, :description] )
end
Form:
<%= simple_form_for #person do |f| %>
<%= f.input :name %>
<%= f.input :email %>
<%= simple_fields_for :diseases do |my_disease| %>
<%= my_disease.input :description %>
<% end %>
<%= f.button :submit %>
<% end %>
Thanks a lot for your help.
The issue is with line <%= simple_fields_for :diseases do |my_disease| %>.It should be
<%= f.simple_fields_for :diseases do |my_disease| %>
This should work.
<%= simple_form_for #person do |f| %>
<%= f.input :name %>
<%= f.input :email %>
<%= f.simple_fields_for :diseases do |my_disease| %> #here
<%= my_disease.input :description %>
<% end %>
<%= f.button :submit %>
<% end %>
For more Info,see this API

Instantiate empty model in partial view?

What is the proper way to have a form in a partial view reference an empty model in order to handle validation properly as defined on the model. Should I instantiate a new, empty model in the partial view and pass it through to the form? Here is what I'm working with...
MODEL
class NewsletterSignup < ActiveRecord::Base
def self.columns()
#columns ||= [];
end
def self.column(name, sql_type = nil, default = nil, null = false)
columns << ActiveRecord::ConnectionAdapters::Column.new(name, default, sql_type, null)
end
def persisted?
false
end
column :first_name, :string
column :last_name, :string
column :email, :string
column :zip, :string
validates :first_name, :last_name, :email, :zip, :presence => true
validates :email, :format => /^[-a-z0-9_+\.]+\#([-a-z0-9]+\.)+[a-z0-9]{2,4}$/i
validates :zip, :format => /^\d{5}$/
end
Partial View
<%
signup = newsletter_signup.new
%>
<%= simple_form_for(signup, ...) do |f| %>
<%= f.input :first_name, :label => "First Name:" %>
<%= f.input :last_name, :label => "Last Name:" %>
<%= f.input :email, :label => "Email:" %>
<%= f.input :zip, :label => "Zip:" %>
...
<% end %>
But I can't seem to instantiate a new model like this. I assume I have to reference it in the view. (Note, I'm new to rails but have a decade+ of professional software development experience, so I apologize if some of rails constructs seem foreign to me and I may just be overlooking something simple!)
If your controller looks like this
def new
Model.new
end
def create
#model = Model.new(params[:model])
if #model.save
redirect root_path, notice: "Saved"
else
render action: 'new'
end
end
def edit
Model.find(params[:id])
end
def update
if #model.update(params[:model])
redirect root_path, notice: "Updated"
else
render action: 'edit'
end
end
You can have views like:
# new.html.erb
<%= render 'form' %>
# edit.html.erb
<%= render 'form' %>
# _form.html.erb
<%= form_for #model do |f| %>
<%= f.label :name %>
<%= f.text_field :name %>
...
<% end %>

Rails associated model is not updating in database

I'm trying to update my associated model, but it's not updating to the database and i'm not sure what to try next.
Model
class User < ActiveRecord::Base
attr_accessible :email, :password, :password_confirmation,
:remember_me, :username, :login, :first_name,
:last_name, :home_phone, :cell_phone,
:work_phone, :birthday, :home_address,
:work_address, :position, :company, :user_details
has_one :user_details, :dependent => :destroy
accepts_nested_attributes_for :user_details
end
class UserDetails < ActiveRecord::Base
belongs_to :user
attr_accessible :home_phone, :position
end
Controller
# PUT /contacts/1/edit
# actually updates the users data
def update_user
#userProfile = User.find(params[:id])
respond_to do |format|
if #userProfile.update_attributes(params[:user])
format.html {
flash[:success] = "Information updated successfully"
render :edit
}
else
format.html {
flash[:error] = resource.errors.full_messages
render :edit
}
end
end
end
View
<%= form_for(#userProfile, :url => {:controller => "my_devise/contacts", :action => "update_user"}, :html => {:class => "form grid_6"}, :method => :put ) do |f| %>
<%= f.label :username, "Username" %>
<%= f.text_field :username, :required => "required" %>
<%= f.fields_for :user_details do |d| %>
<%= d.label :home_phone, "Home Phone" %>
<%= d.text_field :home_phone %>
<% end %>
<% end %>
<% end %>
Your attr_accessible should accept user_details_attributes, not just user_details.

Can I use my new user form to log in too

This has been asked before to some degree but I couldn't find an actual answer: How can I allow my users to log in via the same form they signup? This is a client request/demand by the way, I realise this is far from ideal...
User
class UsersController < ApplicationController
def new
#user = User.new
end
def create
#user = User.new(params[:user])
if #user.save
sign_in #user
render :json => #user.to_json(:only => [:id])
else
render :json => #user.errors, :status => ""
end
end
end
Session
class SessionsController < ApplicationController
def create
user = User.find_by_email(params[:session][:email])
if user && user.authenticate(params[:session][:email])
sign_in user
render :json => #user.to_json(:only => [:id])
else
render :json => #user.errors, :status => ""
end
end
end
Form
<%= form_for(#user, :html => { :class => "access"}) do |f| %>
<%= f.label :firstname, "Firstname" %>
<%= f.text_field :firstname, :placeholder => "Your firstname" %>
<%= f.label :surname, "Surname" %>
<%= f.text_field :surname, :placeholder => "Your surname" %>
<%= f.label :email, "Email Address" %>
<%= f.text_field :email, :placeholder => "Your email address" %>
<%= f.submit "Verify" %>
<% end %>
Emails are validated as unique, could that be an entry point? Eg. If the email is not unique check the name and email or something.
I have no idea how to go about this.
My suggestion is to make another controller which is something like AccessController. It should use a name that means both login and register, Access was just all I could think of. That controller should be able to do a check on the login credentials and either login or register.

Nested model, update_attributes not working

I am having a hard time with what I thought would be an textbook update example. Searched SO but couldn't find the answer. In short, when I click submit the user_id in the profile model gets wiped out and no other data gets saved. I am using Rails 3.2.2.
Here is what I have...
User model...
class User < ActiveRecord::Base
attr_accessible :email, :password, :password_confirmation, :profile_attributes
has_one :profile
accepts_nested_attributes_for :profile
end
Profile model...
class Profile < ActiveRecord::Base
validates :first_name, :presence => true
validates :last_name, :presence => true
belongs_to :user
attr_accessible :first_name, :last_name
end
Users controller...
class UsersController < ApplicationController
def new
#user = User.new
#user.accounts_users.build()
#user.build_profile()
respond_to do |format|
format.html # new.html.erb
format.json { render json: #user }
end
end
def edit
#user = User.find(params[:id])
end
def update
#user = User.find(params[:id])
respond_to do |format|
if #user.update_attributes(params[:user])
format.html { redirect_to #user, notice: 'Profile was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
end
Nested form...
<%= form_for #user, :validate => true do |f| %>
<%= f.fields_for :profile do |p| %>
<fieldset>
<div class="field">
<%= p.label :first_name %>
<%= p.text_field :first_name %>
</div>
<div class="field">
<%= p.label :last_name %>
<%= p.text_field :last_name %>
</div>
<% end %>
<div class="field">
<%= f.label :email %>
<%= f.text_field :email %>
</div>
<div class="actions">
<%= f.submit 'Edit Profile', :class => "btn btn-large btn-success" %>
<%= cancel %>
</div>
</fieldset>
<% end %>
Edit: I edited the UsersController to include the new action. Why would the new action affect the edit/update actions?
I had a similar problem before. Can we see the code for your new action? Do you have #user.build_profile in there (right beneath #user = User.new)? Or is the new action working fine?

Resources