Validation doesn't work as expected for related models in Rails 4? -
i use 1 form enter data 2 models. when save parent model (tenant) child model (user) gets saved, if don't validate tenant_id in user model. if validates :tenant_id, presence: true in user model validation error "users tenant can't blank" displayed. ideas why?
tenant model:
class tenant < activerecord::base has_many :users, dependent: :destroy, inverse_of: :tenant accepts_nested_attributes_for :users before_validation self.status = 0 self.name = name_orig.upcase email.downcase! end validates :name_orig, presence: true, length: { maximum: 255 } validates :name, uniqueness: { case_sensitive: false } valid_email_regex = /\a[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i validates :email, presence: true, length: { maximum: 255 }, format: { with: valid_email_regex }, uniqueness: { case_sensitive: false } validates :status, presence: true end user model:
class user < activerecord::base belongs_to :tenant, inverse_of: :users validates_presence_of :tenant before_validation self.status = 0 self.email = email.downcase end valid_username_regex = /\a\w+\s?\w*\z/i validates :name, presence: true, length: { maximum: 50 }, format: { with: valid_username_regex }, uniqueness: { case_sensitive: false } valid_email_regex = /\a[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i validates :email, presence: true, length: { maximum: 255 }, format: { with: valid_email_regex }, uniqueness: { case_sensitive: false } has_secure_password validates :password, presence: true, length: { minimum: 6 } validates :tenant_id, presence: true validates :status, presence: true end tenant controller:
class tenantscontroller < applicationcontroller def new @tenant = tenant.new @tenant.users.build end def create @tenant = tenant.new(tenant_params) @tenant.save if @tenant.save flash[:success] = "welcome!" redirect_to @tenant # redirects tenant profile else render 'new' end end private def tenant_params params.require(:tenant).permit(:name_orig, :email, users_attributes: [:name, :email, :password, :password_confirmation]) end end signup form:
<%= form_for(@tenant) |f| %> <%= render 'shared/tenant_error_messages' %> <%= f.label :name_orig, "company name" %> <%= f.text_field :name_orig, class: 'form-control' %> <%= f.label :email, "company e-mail" %> <%= f.email_field :email, class: 'form-control' %> <%= f.fields_for(:users) |u| %> <%= u.label :name, "user name" %> <%= u.text_field :name, class: 'form-control' %> <%= u.label :email, "user e-mail" %> <%= u.email_field :email, class: 'form-control' %> <%= u.label :password, "password" %> <%= u.password_field :password, class: 'form-control' %> <%= u.label :password_confirmation, "password confirmation" %> <%= u.password_field :password_confirmation, class: 'form-control' %> <% end %> <%= f.submit "save", class: "btn btn-primary" %> <% end %>
since using nested attributes , saving both models @ same time, cannot validate tenant_id user since persisted in transaction.
because tenant not persisted, not yet have id. since not have id, there cannot tenant_id user.
in case validating tenant_id pointless, because cannot persist user without tenant since user being built on top of tenant. if user persisted, corresponding tenant present.
in case mentioned, users can sign on independent form -
to validate tenant associated in create action use:
tenant = tenant.find_by(params[:tenant_id]) user = tenant.users.build(user_params) instead of
user = user.new(user_params)
this way not have orphan children
Comments
Post a Comment