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