【问题标题】:Rails using build with checkbox with has_one associationRails 使用带有 has_one 关联的复选框的构建
【发布时间】:2015-08-19 20:18:56
【问题描述】:

我有一个拥有个人资料的用户,但并非所有用户都需要个人资料。我正在寻找一种仅在用户表单上选中复选框(通过更新或创建)时创建配置文件的方法。

我的模型看起来像这样 -

class User < ActiveRecord::Base
has_one :profile
accepts_nested_attributes_for :profile

class Profile < ActiveRecord::Base    
belongs_to :user

理想情况下,在我的用户表单中,我想包含一个复选框,选中后会创建配置文件并将配置文件中的 user_id 设置为相应的用户 ID。

我知道在我的用户控制器中,正在做

@user.build_profile

将在更新时创建个人资料,但同样,并非所有用户都需要创建个人资料。

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 has-one


    【解决方案1】:

    我正在尝试类似的东西(使用 Rails 4.2.4)并得出了这个解决方案。

    app/models/user.rb

    allow_destroy: true 将允许您通过用户表单(更多 here)销毁配置文件关联。

    class User < ActiveRecord::Base
    has_one :profile
    accepts_nested_attributes_for :profile, allow_destroy: true
    

    app/controllers/users_controller.rb

    您需要构建用户的关联配置文件实例(在newedit 方法中)才能在各自的表单中正常工作。

    编辑用户时,可能已经存在个人资料关联。 edit 方法将使用关联的配置文件(如果存在)(使用其值设置表单),否则创建一个新的配置文件实例。

    还要注意user_params 包括profile_attributes: [:_destroy, :id],这将是复选框发送的值。

    def new
      @user = User.new
      @user.build_profile
    end
    
    def create
      @user = User.new(user_params)
      if @user.save
        redirect_to root_path
      else
        render :new
      end
    end
    
    def edit
      @user.profile || @user.build_profile
    end
    
    def update
      if @user.update(user_params)
        redirect_to @user
      else
        render :edit
      end
    end
    
      private
    
      def user_params
        params.require(:user).permit(:name, profile_attributes: [:_destroy, :id])
      end
    

    app/views/users/new.html.rbapp/views/users/edit.html.rb

    使用表单中的fields_for 方法为关联提交数据(更多关于嵌套属性,特别是一对一关系,here)。

    使用复选框destroy 属性来创建/销毁关联的配置文件。花括号内的checked 属性的值根据关联是否存在设置复选框的默认状态(更多在“更复杂的关系”标题here 下)。后面的'0''1' 反转了destroy 方法(即,如果选中复选框则创建关联,如果没有选中则删除它)(更多here)。

    <%= form_for @user do |user| %>
    
      <%= user.fields_for :profile do |profile| %>
        <div class='form-item'>
          <%= profile.check_box :_destroy, { checked: profile.object.persisted? }, '0', '1' %>
          <%= profile.label :_destroy, 'Profile', class: 'checkbox' %>
        </div>
      <% end %>
    
      <%= user.submit 'Submit', class: 'button' %>
    
    <% end %>
    

    您也可以从配置文件模型中删除主键 id,因为在这种情况下这是不必要的,而 link 在这方面非常有用。

    【讨论】:

      【解决方案2】:

      在您的表单中创建一个复选框,但不要使用 form_for 符号 'f'。而是使用 check_box_tag

      check_box_tag :create_profile
      

      如果选中此框,现在在您的创建/更新功能中创建配置文件

      @user.build_profile  if params[:create_profile]
      

      【讨论】:

      • 如果访问编辑用户页面,如果用户与个人资料有现有关联,上述似乎没有预先选中该框,这肯定是所需的行为?
      猜你喜欢
      • 2011-01-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-23
      • 2011-04-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多