Rails - 提交表单时未创建新字段

Posted

技术标签:

【中文标题】Rails - 提交表单时未创建新字段【英文标题】:Rails - new fields not getting created on form submission 【发布时间】:2021-10-29 08:10:48 【问题描述】:

所以我有以下模型。具有以下定义的用户、团队和成员

用户

class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
        :recoverable, :rememberable, :validatable

  belongs_to :current_team, class_name: "Team", optional: true
  has_many :memberships
  has_many :teams, through: :memberships
  has_many :owner_memberships, ->  where(role: :owner) , class_name: "Membership"
  has_many :owned_teams, through: :owner_memberships, source: :team

  def membership_for(team)
    memberships.where(team: team).take
  end
end

团队

class Team < ApplicationRecord
    has_many :memberships
    has_many :users, through: :memberships
    has_one :owner_membership, ->  where(role: :owner, status: :active) , class_name: "Membership"
    has_one :owner, through: :owner_membership, source: :user
end

会员

class Membership < ApplicationRecord
  belongs_to :user
  belongs_to :team

end

使用脚手架生成的所有表单都可以正常工作。我现在面临的问题是,我在 Membership 模型中添加了 2 个额外的字段,RoleStatus,这意味着成员资格类现在如下所示,但我正在努力将这些字段传递到数据库。

class Membership < ApplicationRecord
  belongs_to :user
  belongs_to :team

  enum status: [:pending, :active]

  enum role: [:owner, :admin, :user]
  
  def owner_or_admin?
    owner? || admin?
  end
end

当我查看rails s 的控制台时,我可以看到以下内容,这表明新字段不是作为成员资格定义的一部分而是作为单独的参数发送的。如何让他们正确发送和创建

Processing by MembershipsController#create as html
    Parameters: 
        "authenticity_token"=>"5gzC/7YLIzqb+uNqHi2izth07MPv4WXrF49444+2bK7ML7ceLwk+BR2tP9fHiqCVJFJrxJHjuaz7dXxcp0yq0A==", 
        "membership"=>"user_id"=>"2", "team_id"=>"1", 
        "role"=>"0", 
        "status"=>"0", 
        "commit"=>"Create Membership"
    


Membership Create (1.3ms)  INSERT INTO "memberships" ("user_id", "team_id", "created_at", "updated_at") VALUES (?, ?, ?, ?)  [["user_id", 2], ["team_id", 1], ["created_at", "2021-08-30 14:58:03.929323"]

编辑:为表单添加视图

<%= form_with(model: membership, local: true) do |form| %>
  <% if membership.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(membership.errors.count, "error") %> prohibited this membership from being saved:</h2>

      <ul>
        <% membership.errors.full_messages.each do |message| %>
          <li><%= message %></li>
        <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= form.label :user_id %>
    <%= form.collection_select :user_id, User.order(:email),:id,:email, include_blank: true %>

  </div>

  <div class="field">
    <%= form.label :team_id %>
    <%= form.collection_select :team_id, Team.where(id: current_team.id),:id,:name, :selected => current_team %>

  </div>

  <div class="field">
    <%= form.label :role %>    
    <%= select_tag :role, options_for_select(Membership.roles.map |k, v| [k.humanize.capitalize, v]) %>
  </div>

  <div class="field">
    <%= form.label :status %>    
    <%= select_tag :status, options_for_select(Membership.statuses.map |k, v| [k.humanize.capitalize, v]) %>
  </div>

  <div class="actions">
    <%= form.submit %>
  </div>
<% end %>

【问题讨论】:

你能添加视图/表单的样子吗?问题似乎在于表单如何为 create 构建 POST 参数 对于ActiveRecord::Enum,您应该传递枚举键"role"=&gt;"admin",而不是整数值,这是一个内部实现细节,只有模型才能知道。 【参考方案1】:

首先设置一个方法,将枚举状态作为[label, value] 对的数组提供给您,适合构建选择器、复选框或单选按钮:

module EnumHelper
  # creates an array of [label, value] pairs from an enum
  # the translations can be customized through for example:
  # -  membership.statuses.active
  # -  membership.roles.active
  def options_from_enum(klass, name)
    i18n_scope = "#klass.model_name.i18n_key.#name"
    klass.public_send(name).map do |key|
      label = I18n.t(
        key,
        default: key.to_s.humanize
        scope: i18n_scope 
      )
      [label, key]
    end
  end
end

请注意,您从表单传递的值应该是枚举状态的名称(“待定”),而不是整数(“0”),它是一个只有模型才能知道的内部实现细节。

然后确保从表单构建器中创建输入:

<%= form_with(model: @membership) do |form| %>
  <div class="field">
    <%= form.label :role %>
    <%= form.select :role, options_from_enum(Membership, :roles) %>
  </div>
  <div class="field">
    <%= form.label :status %>
    <%= form.select :status, options_from_enum(Membership, :statuses) %>
  </div>
 
  # ...
<% end %>

【讨论】:

以上是关于Rails - 提交表单时未创建新字段的主要内容,如果未能解决你的问题,请参考以下文章

表单输入的值在 React 中提交时未更新

ExtJs,提交表单时未调用自定义TextField的getValue()函数

Rails将表单提交链接到对象

在提交失败时保持 jQuery - Rails

不允许用户在 ruby​​ on rails 中提交带有空字段的表单

未定义的方法 - 提交表单后属性为 NULL (Rails 3.2.13)