In our rails 3.1.4 app, there are user (parent) and user_levels (child) models.
class User < ActiveRecord::Base
attr_accessible :name, :login, :password, :user_levels_attributes, :as => :role_new
has_many :user_levels
ccepts_nested_attributes_for :user_levels, :allow_destroy => true, :reject_if => proc { |a| a['position'].blank? }
validates_associated :user_levels
end
class UserLevel < ActiveRecord::Base
belongs_to :user
validates_presence_of :position
end
The position column in user_level has to be filled. If it is not, both user and user_levels should NOT be saved. The problem with the above is that it always causes error of “position can’t be blank” even there is a position value in the params.
{"utf8"=>"✓",
"user"=>{"name"=>"tester ceo",
"login"=>"testceo",
"update_password_checkbox"=>"[FILTERED]",
"password"=>"[FILTERED]",
"password_confirmation"=>"[FILTERED]",
"user_levels_attributes"=>{"1339886115748"=>{"position"=>"ceo"}}},
"commit"=>"Save"}
After deleting user_levels_attribues, the model saves user into users table no matter what kind of user_levels is filled int. We did extensive online search and haven’t found a solution yet. For example, if validates_presence_of :user_levels is added to the user model, then none of the user levels can be saved or updated, even with a valid position.
Any suggestion about how to implement the orchestrated saving/updating of two associated models? Thanks so much.
UPDATE:
_user_level.html.erb:
<div class="fields">
<%= f.input :position, :collection => return_position, :prompt => "Choose position",
:label => false, :include_blank => true, :selected => i_id %>
<%= link_to_remove_fields "remove", f %>
</div>
_form_new.html.erb:
<%= simple_form_for @user do |f| %>
<%= f.input :name, :label => 'name:' %>
<%= f.input :login, :label => 'login:', :hint => '6 digits ' %>
<%= f.input :password, :label => 'password:', :hint => '6digits', :input_html => {:id => 'new_user_password'} %>
<%= f.input :password_confirmation, :label => 'confirmation:' %>
<%= f.input :user_type, :label => 'user type:', :collection => return_user_type, :include_blank => true %>
position:
<p><%= link_to_add_fields "Choose position", f, :user_levels %></p>
<p><%= f.button :submit, 'Save' %></p>
<% end %>
Here is the method to add position field:
#add user position in system user creation
def link_to_add_fields(name, f, association)
new_object = f.object.class.reflect_on_association(association).klass.new
fields = f.fields_for(association, new_object, :child_index => "new_#{association}") do |builder|
render :partial => association.to_s, :locals => {:f => builder, :i_id => 0}
end
link_to_function(name, "add_fields(this, \"#{association}\", \"#{j fields}\")")
end
JS file:
function add_fields(link, association, content) {
var new_id = new Date().getTime();
var regexp = new RegExp("new_" + association, "g")
$(link).parent().before(content.replace(regexp, new_id));
}
I think you need to remove the
:reject_ifand changevalidates_associated :user_levelstovalidates_presence_of :user_levels.