RoR 5 find_or_initialize_by以嵌套的形式在has_many关系中保存

时间:2016-12-09 04:36:31

标签: ruby-on-rails forms nested-forms ruby-on-rails-5 has-many-through

我有一种感觉,我错过了一些明显的东西......

Usergrant记录不能通过表单保存或更新(用户#更新)。

许多用户可以通过联接表Usergrants

与许多Grants相关联
    class User < ActiveRecord::Base
      has_many :usergrants
      has_many :grants, through: :usergrants
      accepts_nested_attributes_for :usergrants, allow_destroy: true


    class Grant < ApplicationRecord
      validates_presence_of :name
      has_many :usergrants
      has_many :users, through: :usergrants
    end


    class Usergrant < ApplicationRecord
      belongs_to :user
      belongs_to :grant
      validates :user_id, :grant_id, :active, :percent, presence: true
    end

控制器(有强参数):

def edit
  @title = "Edit User"

  @user = User.find(params[:id])
  @grants = Grant.all.where(active: true)

  if current_user == @user
    @page_title = "Edit your profile"
  else
    @page_title = "Edit "+@user.fname+"\'s profile"
  end

  if current_user.can_approve_this?(@user)
    @disabled = false
    @readonly_shower = "readonly-shower"
  else
    @disabled = true
    @readonly_shower = ""
  end

  @active_def = @user.active
  @salary_def = @user.pay_type
  @super_array = super_array
  @dept_array = dept_array
  @pw_lang = "Change password"
  session[:return_url] = back_uri

  if @user.pay_type == "Salary"
    @salary_hider = ""
    @hourly_hider = "hidden"
  else
    @salary_hider = "hidden"
    @hourly_hider = ""
  end
end

def update
  @user = User.find(params[:id])
  @grants = Grant.all.where(active: true)

  @user.salary_rate == 0.0 if @user.salary_rate.nil?
  @user.hourly_rate == 0.0 if @user.hourly_rate.nil?

  if @user.update_attributes(user_params)
    flash[:success] = "Profile updated"
    redirect_to session[:return_url]
  else
    @dept_array = dept_array
    @super_array = super_array
    render 'edit'
  end
end

def user_params
  params.require(:user).permit(
    :id, :fname, :lname, :active,
    ...
    :usergrants_attributes => [:id, :user_id, :grant_id, :active, :percent])
end

用户表单:

<%= form_for( @user, remote: true) do |f| %>
...
  <% @grants.each do |grant| %>
    <%= f.fields_for :usergrant, @user.usergrants.find_or_initialize_by(user: @user, grant: grant) do |ug| %>
    ...
      <%= grant.name %>
      <%= ug.text_field :user_id, value: user.id %>
      <%= ug.text_field :grant_id, value: grant.id %>
      <%= ug.text_field :active %>
      <%= ug.text_field :percent %>
    <% end %>
  <% end %>
...
<% end %>

我可以在控制台中创建Usergrant记录,它们会在表单中按预期显示。 User.usergrantGrant.usergrant正在按预期执行。

这是日志:

    Parameters: {"utf8"=>"✓", "authenticity_token"=>"...", "user"=>{"id"=>"1", 
"fname"=>"Chip", "lname"=>"...", "email"=>"...", "time_zone"=>"Eastern Time (US & 
Canada)", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]", 
"usergrants_attributes"=>{"0"=>{"id"=>"2", "user_id"=>"1", "grant_id"=>"1", "active"=>"0", 
"percent"=>"0.0"}, "1"=>{"id"=>"1", "user_id"=>"1", "grant_id"=>"4", "active"=>"1", 
"percent"=>"25.0"}, "2"=>{"id"=>"3", "user_id"=>"1", "grant_id"=>"5", "active"=>"0", 
"percent"=>"0.0"}}}, "id"=>"1"}

我的缺点是什么?

2 个答案:

答案 0 :(得分:2)

好的,在@Arslan_Ali和@crazy_vine的帮助下,我能够征服它。

首先,我错过了accepts_nested_attributes_for电话。

其次,我必须复数<%= f.fields_for :usergrants %>

第三,我意识到我可以简化这个:<%= f.fields_for :usergrant, @user.usergrants.find_or_initialize_by(grant: grant) do |ug| %>(摆脱user: @user

第四,我必须允许users_params中的User.id,不知道为什么,但是日志告诉我ID被连接到我的连接表被拒绝。

第五,我遇到了我无法看到的表单错误,因为我的顶层表单已设置为remote: true,删除此错误表明Usergrant.activeUsergrant.percent错误。我调整了我的验证并在我的列中添加了默认值。

Stuff现在像帮派破坏者一样工作。感谢明智的指导,伙计们!

答案 1 :(得分:1)

由于用户有很多UserAgent个对象,因此您需要在accepts_nested_attributes_for模型中编写User

accepts_nested_attriubtes_for :user_agents

只有这样,您才能为给定用户创建或修改现有的UserAgent个对象。

修改

您正在做的另一件事是:<%= f.fields_for :usergrant。由于User模型有许多Usergrants,因此它必须是复数,如下所示:

<%= f.fields_for :usergrants  %>