我有一个项目,用户和项目之间存在has_and_belongs_to_many关系。我尝试使用项目表单上的复选框创建项目以选择用户,但它在保存阶段失败并显示错误Users is invalid
。
我的用户模型是:
class User < ActiveRecord::Base
has_and_belongs_to_many :projects
devise :database_authenticatable,
:recoverable,
:rememberable,
:trackable,
:lockable,
:timeoutable
validates :username,
presence: true,
length: { minimum: USER_NAME_MIN_LENGTH,
maximum: USER_NAME_MAX_LENGTH },
allow_blank: false,
allow_nil: false,
uniqueness: { case_sensitive: false }
validates_format_of :email,
with: Devise.email_regexp,
if: :email_changed?
validates_presence_of :password,
on: :create
validates_confirmation_of :password
validates_length_of :password,
within: Devise.password_length
validates_presence_of :role
我的项目模型是:
class Project < ActiveRecord::Base
has_and_belongs_to_many :users
validates :name,
uniqueness: true,
presence: true,
length: {within: 1..PROJECT_NAME_MAX_LENGTH}
validates :base_year,
presence: true,
numericality:
{only_integer: true,
greater_than_or_equal_to: BASE_YEAR_MIN,
less_than_or_equal_to: BASE_YEAR_MAX}
validates :client, length: {maximum: CLIENT_NAME_MAX_LENGTH}
validates :work_order, length: {maximum: WORK_ORDER_MAX_LENGTH}
end
我的表单视图(HAML)是:
= form_for(project) do |f|
- if project.errors.any?
#error_explanation
%h2
= pluralize(project.errors.count, "error")
prevented this project being saved:
%ul
- project.errors.full_messages.each do |message|
%li= message
%table
%tr.field
%td= f.label :name
%td= f.text_field :name
%tr.field
%td= f.label :base_year
%td= f.number_field :base_year
%tr.field
%td= f.label :work_order
%td= f.text_field :work_order
%tr.field
%td= f.label :client
%td= f.text_field :client
%tr.field
%td= f.label :active
%td= f.check_box :active
%h2 Users
- User.all.each do |user|
%td= check_box_tag 'project[user_ids][]', user.id, @project.users.include?(user)
%td= user.username
.actions
= f.submit 'Save'
我已经将一些调试打印语句放入项目控制器中,以查看它出错的地方。该控制器的创建部分是:
def create
@project = Project.new(project_params)
@project.users.each do |user|
puts "=== User: #{user.username}"
end
respond_to do |format|
if @project.save then
# Print statement for debugging
puts '=== Save success'
on_save_success(format,
Project,
@project,
notice: 'Project was successfully created.')
else
# Print statement for debugging
puts '=== Save fail'
on_save_fail(format, @project.errors)
end
end
end
行@project = Project.new(project_params)
似乎成功,后续块正确显示我在表单上检查过的所有用户(实际上只有一个),但保存是失败。控制台输出是:
Started POST "/projects" for 127.0.0.1 at 2016-01-25 16:11:18 +0000
Processing by ProjectsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"S4Kawr8r7nVlpZdimAcvkER0lB70UQZ1zOoo8/82g4g=", "project"=>{"name"=>"Test", "base_year"=>"2000", "work_order"=>"", "client"=>"", "active"=>"0", "user_ids"=>["1"]}, "commit"=>"Save"}
User Load (0.5ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 1]]
=== User: alice
(0.0ms) begin transaction
User Exists (0.0ms) SELECT 1 AS one FROM "users" WHERE (LOWER("users"."username") = LOWER('alice') AND "users"."id" != 1) LIMIT 1
Project Exists (0.0ms) SELECT 1 AS one FROM "projects" WHERE "projects"."name" = 'Test' LIMIT 1
(1.0ms) rollback transaction
=== Save fail
我无法看到它对用户的反对意见 - 对它们没有任何验证。我究竟做错了什么?
编辑: 我无法解决如何添加调试器的问题,所以我只是将@ project.valid和@project_errors作为调试打印语句:
@project = Project.new(project_params)
puts "=== Project is #{@project.valid? ? "" : "not "} valid"
puts "=== Errors:"
puts @project.errors.full_messages.to_sentence
结果是:
Started POST "/projects" for 127.0.0.1 at 2016-01-29 16:06:13 +0000
Processing by ProjectsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"WAIMP+Z/g0bKFWhh/DUcroMooJoPTsUx3A9y6XZCJWk=", "project"=>{"name"=>"Test", "base_year"=>"2000", "work_order"=>"", "client"=>"", "active"=>"1", "user_ids"=>["1"]}, "commit"=>"Save"}
User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 1]]
User Exists (1.0ms) SELECT 1 AS one FROM "users" WHERE (LOWER("users"."username") = LOWER('alice') AND "users"."id" != 1) LIMIT 1
Project Exists (1.0ms) SELECT 1 AS one FROM "projects" WHERE "projects"."name" = 'Test' LIMIT 1
=== Project is not valid
=== Errors:
Users is invalid
(0.0ms) begin transaction
CACHE (0.0ms) SELECT 1 AS one FROM "users" WHERE (LOWER("users"."username") = LOWER('alice') AND "users"."id" != 1) LIMIT 1
CACHE (0.0ms) SELECT 1 AS one FROM "projects" WHERE "projects"."name" = 'Test' LIMIT 1
(0.0ms) rollback transaction
=== Save fail
答案 0 :(得分:0)
我已经确认问题是Rails正在尝试验证用户条目,即使不需要验证也失败,因为我验证明文密码的长度,当我保存项目时不存在。因此,我正在关闭此问题,并发布a new question that is more specific to the issue as I now understand it。
答案 1 :(得分:0)
面对相同的问题,我通过以下2项更改解决了该问题
在您的check_box_tag之前添加<%= hidden_field_tag“ project [user_ids] []”,无%>行。
确保您现有的用户有效,如果您添加无效用户,则将显示“用户无效”错误。
答案 2 :(得分:0)
在check_box_tag之前添加以下隐藏标签。
Social
hidden_field_tag允许用户取消选中所有复选框并成功删除所有关联。
或者您可以使用collection_check_boxes
`<%= hidden_field_tag("project[user_ids][]", nil) %>`