Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

serious stuck on: validations not triggered for nested resource with fields_for

Im seriously stuck on an issue where I have a User and Profile model. whatever I try it seems validations are not triggered for any of the Profile attributes

  • The profile model belongs to User. User has_one Profile
  • On registration form using fields_for to have some profile fields displayed ( gender, and city and country )
  • Whatever I tried, I'm unable to let validation work for gender and city ( the fields_for profile fields)

My form:

- title t(:title, :scope => :register)
%h1= yield(:title)

  = simple_form_for(resource, :as => resource_name, :html => { :class => 'form-horizontal' } , :validate => true , :url => registration_path(resource_name)) do |f|

    = f.input :username,                  :label  => t(:username)
    = f.input :email,                     :label  => t(:email),
                                          :hint   => t(:hint_email_visible)
    = f.input :password,                  :label  => t(:password), :require => true
    = f.input :password_confirmation,     :label  => t(:password_confirm)


    - resource.build_profile
    = f.fields_for :profile do |f|

      #div

        = f.hidden_field :form, :value => "signup"

        .clear

        = f.input :gender,                :collection => [['Male', 'male'], ['Female', 'female']],
                                          :as => :radio

    = f.input :city,
              :readonly => "readonly",
              :label => t(:city)

    .ruler

    = f.input :country,
              :label => "Your country",
              :collection => [DataCountry.where(:code => 155).first],
              :value => @city,
              :id => "country",
              :name => "country"

    .clear


    = f.button :submit, t(:submit, :scope => :register) + " »"

My User model has this:

  accepts_nested_attributes_for :profile

My Profile model with validations is like:

  validates_presence_of :gender
  validates_presence_of :city
  validates_presence_of :country

My PARAMS:

-- !ruby/hash:ActiveSupport::HashWithIndifferentAccess
utf8: ✓
authenticity_token: <mytokenhere>
user: !ruby/hash:ActiveSupport::HashWithIndifferentAccess
  invite_code: ''
  username: username
  email: ''
  password: ''
  password_confirmation: ''
  profile_attributes: !ruby/hash:ActiveSupport::HashWithIndifferentAccess
    form: signup
    gender: male
    dob(3i): '9'
    dob(2i): '7'
    dob(1i): '1942'
    city: 'somevalue'
    country: 'somevalue'
commit: Register »
action: create
controller: registrations

Rails console does:

User.new


 => #<User id: nil, email: "", encrypted_password: "", reset_password_token: nil, reset_password_sent_at: nil, remember_created_at: nil, sign_in_count: 0, current_sign_in_at: nil, last_sign_in_at: nil, current_sign_in_ip: nil, last_sign_in_ip: nil, password_salt: nil, confirmation_token: nil, confirmed_at: nil, confirmation_sent_at: nil, unconfirmed_email: nil, failed_attempts: 0, unlock_token: nil, locked_at: nil, authentication_token: nil, username: nil, is_blocked: nil, is_deleted: nil, role: nil, slug: nil, created_at: nil, updated_at: nil, last_seen: nil, credits: nil, invite_code: nil, is_moderated: nil, locale: nil, status: nil, login_token: nil> 

Profile.new

 => #<Profile id: nil, user_id: nil, gender: nil, country: nil, state: nil, city: nil, status: nil, counter_cache: nil> 

-- UPDATE 19 Jul '12

I added the

    - @user.errors.full_messages.each do |message|
  = message
  .clear

To the form to see what exactly is happening and this throws the following list of errors:

Email can't be blank
Email can't be blank
Password can't be blank
Password can't be blank
Profile city can't be blank
Profile gender can't be blank
Profile is invalid
Username can't be blank
Password confirmation can't be blank 

So it seems the validation is checked.... But no error styling is applied! Also the profile is invalid???? Im not sure but does that refer to the

like image 310
Rubytastic Avatar asked Jul 08 '12 12:07

Rubytastic


2 Answers

First off, the params that you pasted include values for the profile's city, country and gender. If this is accurate, then validation should pass, because the Profile model validates the presence of these 3 fields -- and they are present.

I also note that you're doing resource.build_profile in the view, which should build up a default profile belonging to the user. If any values are being assigned in the profile during instantiation, this would cause them to make their way into the form, and ultimately into the params hash.

So my guess is that you're populating the fields somewhere along the line, perhaps in the User or Profile models. You should check those again, particularly during initialization of a new profile.

That's all I can guess at from the data you've given. If you still can't find the issue, you could try committing it (or a separate app which reproduces the issue, if you're uncomfortable sharing your real app) to GitHub so that we can analyze the issue more directly.

EDIT: just noticed, in your bounty you wrote:

anyone can provide a working example [of] nested resources and validations

So, see https://github.com/sinisterchipmunk/rubytastic for a simple example of user validation with nested attributes for a Profile, modeled after your question. It validates User#email, Profile#city, Profile#country and Profile#gender.

like image 197
sinisterchipmunk Avatar answered Nov 06 '22 17:11

sinisterchipmunk


Check whether you have any default value in the database set.It seems that in the form params, you have pasted in the question, gender has value male passed. Is this form params passed even when you didnt check anything for gender? In that case, this must be a case where the gender field in the database must have the default value for gender as male. In that case, even a new Profile model object will have its gender attribute as male, and so it will pass the validations and save the gender as male in the database. For example, I have a boolean field is_admin in the users table and set its default value as false or 0. Then if I do this:

User.new
=>  #<User id: nil, name: nil, email: nil, is_admin: false>

You can see the is_admin attribute is set to false instead of nil. Now if we do not pass any value for is_admin, here it will be saved as false in the database and also will not trigger the validation for is_admin field, as it is present in the object's attributes (with value false).

like image 29
rubyprince Avatar answered Nov 06 '22 16:11

rubyprince