Reputation: 281
I am following the Rails Tutorial doing a little project for myself and then try to progress.
Well I am facing a problem for which I found the solution, but I'll really appreciate any thoughts and opinions because to make it work I have to disable a validation in an association.
The context is as follow : the application (big name for what it does actually...) has users to track their weight. I would like that when a user sign up, he/she enters a first measure on the go.
So here are the simplified models:
User.rb
class User < ActiveRecord::Base
attr_accessible :email, :name, :password, :password_confirmation, :measures_attributes
has_secure_password
has_many :measures, dependent: :destroy
accepts_nested_attributes_for :measures
# here goes validations before_save, etc. taken from the Rails Tutorial
end
Measure.rb
class Measure < ActiveRecord::Base
attr_accessible :weight
belongs_to :user
# This is kind where the problem is...
# If I deactivate the validation for user_id everyhing goes fine
validates :user_id, presence: true
validates :weight, presence: true, numericality: { greater_than: 0 }
default_scope order: 'measures.created_at ASC'
end
Here is the Users controller
class UsersController < ApplicationController
# GET /users/new
def new
@user = User.new
@user.measures.build
end
# POST /users
def create
@user = User.new(params[:user])
if @user.save
sign_in @user
flash[:success] = "Hi #{@user.name}. Welcome !"
redirect_to @user
else
render :new
end
end
end
Here is the form partial for the user :
<%= form_for(user) do |user_form| %>
<%= render 'shared/error_messages', object: user_form.object %>
<%= render 'users/fields', user_builder: user_form %>
<%= user_form.fields_for :measures do |measure_fields| %>
<%= render 'measures/fields', measure_builder: measure_fields, full: true %>
<% end %>
<%= user_form.submit submit_text, class: 'btn btn-large btn-primary' %>
<% end %>
And even when I fill the form correctly, I get this error :
* Measures user can't be blank
The only way I found to make it work is to get rid of the :user_id validation for presence in the Measure model. I want to emphasize that when this validation is off, the user is saved, the measure is saved and correctly associated with the newly created user.
Am I doing something wrong ? Is the :user_id presence validation in the Measure model really useful (it is in the Rails Tutorial and it makes perfectly sense for me) ? If yes why is the Measure validation failing when it is on ?
Thanks a lot in advance.
Upvotes: 0
Views: 371
Reputation: 2488
You could try validates :user
instead of user_id
. Then it might work out that the two are associated in memory even though the User hasn't been saved yet.
Upvotes: 1
Reputation: 2228
I think I may have found an error in your code that would cause the error you're seeing.
In your new controller you specifically create an association:
@user.measures.build
In your create controller, you create a new element based on the fields that were passed in.
@user = User.new(params[:user])
There are some cases where the associated element will be dropped. I can't remember if this happens by default if it doesn't validate or if there was an option you need to set to make it drop.
I think you may need to add
@user.measure.build if @user.measures.empty?
in your create
controller else
clause before render :new
.
I don't know if you're actually hitting this problem, but it would explain why the association to your User
wasn't set.
Upvotes: 0