【问题标题】:Forms for has_one but not alwayshas_one 的形式,但并非总是如此
【发布时间】:2019-11-29 19:02:37
【问题描述】:

我有两个模型:PersonUser。一个人可以有一个用户或根本没有用户,但每个用户都必须属于一个人。

我已经这样设置了两个模型:

Person(具有 has_user 属性):

has_one :user, dependent: :destroy
accepts_nested_attributes_for :user

用户(具有 person_id 属性):

belongs_to :person
validates_presence_of :login, :password
validates_uniqueness_of :login

在 Person 表单中,我有一个嵌套的 form_for,只有当我选中一个复选框,该复选框还在 Person 的表单部分上将 has_user 属性设置为 true 时才会显示。

我的问题是,每当我提交一个没有用户的人时,它仍然会尝试验证用户。我怎样才能让它发挥作用?

更新:

在我看来:

  <div class="form-group">
    <%= person_form.label :has_user, :class => 'inline-checkbox' do %>
      Possui usuário
      <%= person_form.check_box :has_user, {id: "hasUser", checked: @person.has_user} %>
    <% end %>
  </div>
</div>
<div id="userPart" class="findMe"
     <% if @person.user.id.blank? %> style="display:none;"
     <% end %>>
  <h2> User: </h2>
  <div class="container">
    <%= person_form.fields_for :user do |user_form| %>
      <%= render partial: 'users/campos_user', locals: {form: user_form} %>
    <% end %>
  </div>
</div>

在我的 Person.js 中:

jQuery ->
  $(document).ready ->
    $(document).on 'turbolinks:load', #Added line
      console.log("Turbolinks ready.")
      $("#hasUser").change ->
        $("#userPart").toggle();
        return
    return
    return
  return

在我的个人控制器中:

 def new
    @person= Contato.new
    @person.ativo = true
    @page_title = 'Novo person'
    @person.build_user
  end

 def create
    @person = Person.new(person_params)
    respond_to do |format|
      if @person.save
        flash[:notice] = 'Contato foi criado com sucesso.'
        if @person.has_user == true
          format.html {redirect_to controller: :users, action: :new, person_id: @person.id}
        else
          format.html {redirect_to @person}
        end
        format.json {render :show, status: :created, location: @person}
      else
        flash[:warn] = "Erro ao criar contato."
        format.html {render :new}
        format.json {render json: @person.errors, status: :unprocessable_entity}
      end
    end
  end

人的参数:

def person_params
    params.require(:person).permit(:id, :company_id,
                                    :active, :name,
                                    :cargo, :celular,
                                    :email, :nascimento,
                                    :observacoes, :mensagem_instantanea,
                                    :tipo_msg_inst, :possui_usuario,
                                    user_attributes: [:login, :password, :permits, :id, :person_id, :_destroy])
end

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-5 nested-forms nested-attributes accepts-nested-attributes


    【解决方案1】:

    您可以使用reject_if 选项拒绝提交用户属性

    accepts_nested_attributes_for :user, :reject_if => :no_user_connected
    
    def no_user_connected(attributes)
      attributes[:user_attributes][:login].blank?
    end
    

    这应该丢弃表单的用户部分(所有用户属性)。请注意,我不知道您的表单或控制器的外观如何,因此您可能需要以不同的方式构建条件。

    您还可以对用户进行有条件的验证。但总体而言,避免复杂的验证问题的最佳方法是使用某种形式的表单对象来封装验证过程。 https://thoughtbot.com/blog/activemodel-form-objects

    【讨论】:

    • 我可以使用 Person 对象的 has_user 属性吗?因为我试过了,但对我没有用。
    • 你可以试试。也许您可以尝试显示表单和控制器(包括处理参数的方式),以便更容易帮助您解决这个问题?还有什么是你得到的确切错误? ActiveRecord::ValidationError?消息是什么。
    • person_params 的定义是什么?我假设您在那里为嵌套用户传递参数?您还在这些模型上使用 inverse_of 吗?旧版本没有它,它在嵌套模型的情况下非常有用。
    • 添加了问题的参数。是的,我正在使用嵌套属性。
    • 我认为在这种情况下,我会避免在此流程中简单地执行create,并将创建和验证转移到表单对象和服务中。我不知道您在 RoR 方面的经验如何,但控制器应该只是一个调用一些处理对象创建和重定向/呈现页面的外部服务的地方。当您创建一个初始化和验证对象的验证对象时,您可以调用将创建它的服务对象(Person 对象),然后调用另一个服务进行验证,然后创建用户对象。我建议一个我之前发布的链接
    猜你喜欢
    • 1970-01-01
    • 2015-07-01
    • 2013-10-20
    • 2019-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多