尽管在表单中指定了嵌套的body属性,但未插入该属性。尽管票证模型接受:message的嵌套属性,但我收到“ Unpermitted parameter::message”错误。票务控制器还允许message_attributes。
Processing by TicketsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"tTOKOw/q0H8gXyEnaEK8lmwZUAoMsI4QQAt4VTwG8QdtQNZtf8Yj7N6Z0VR6MZbvoUARzp7DG60dI5RuKtP8Fw==", "ticket"=>{"category"=>"Miscellaneous - Project", "deadline"=>"2019-01-13", "message"=>{"body"=>"sdf"}}, "button"=>""}
Unpermitted parameter: :message
(0.2ms) BEGIN
↳ app/controllers/tickets_controller.rb:32
User Load (0.3ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
↳ app/controllers/tickets_controller.rb:32
Ticket Create (0.8ms) INSERT INTO `tickets` (`category`, `deadline`, `created_at`, `updated_at`) VALUES ('Miscellaneous - Project', '2019-01-13', '2019-01-14 00:45:52', '2019-01-14 00:45:52')
↳ app/controllers/tickets_controller.rb:32
Message Create (0.6ms) INSERT INTO `messages` (`user_id`, `ticket_id`, `created_at`, `updated_at`) VALUES (1, 62, '2019-01-14 00:45:52', '2019-01-14 00:45:52')
↳ app/controllers/tickets_controller.rb:32
(116.8ms) ROLLBACK
↳ app/controllers/tickets_controller.rb:32
Completed 500 Internal Server Error in 159ms (ActiveRecord: 120.3ms)
ActiveRecord::NotNullViolation (Mysql2::Error: Field 'body' doesn't have a default value: INSERT INTO `messages` (`user_id`, `ticket_id`, `created_at`, `updated_at`) VALUES (1, 62, '2019-01-14 00:45:52', '2019-01-14 00:45:52')):
app/controllers/tickets_controller.rb:32:in `block in create'
app/controllers/tickets_controller.rb:31:in `create'
new.html.erb
<%= form.fields_for @ticket.message do |message_form| %>
<div class="form-group row">
<div class="col-sm-12">
<%= message_form.label :body %>
<%= message_form.text_area :body, class: "form-control" %>
</div>
</div>
<% end %>
user.rb
class User < ApplicationRecord
devise :database_authenticatable, :registerable, :trackable, :rememberable, :validatable
has_many :messages, inverse_of: :user
has_many :tickets, through: :messages
end
ticket.rb
class Ticket < ApplicationRecord
has_one :message, inverse_of: :ticket
has_many :messages, inverse_of: :ticket
has_many :users, through: :messages
accepts_nested_attributes_for :message
end
message.rb
class Message < ApplicationRecord
belongs_to :user, inverse_of: :messages
belongs_to :ticket, inverse_of: :message
belongs_to :ticket, inverse_of: :messages
validates_presence_of :user, :ticket
end
tickets_controller.rb
def new
@ticket = Ticket.new
@ticket.build_message
end
def create
@ticket = Ticket.new(ticket_params)
@ticket.build_message(:user_id => current_user.id)
respond_to do |format|
if @ticket.save
format.html { redirect_to @ticket, notice: 'Ticket was successfully created.' }
format.json { render :show, status: :created, location: @ticket }
else
format.html { render :new }
format.json { render json: @ticket.errors, status: :unprocessable_entity }
end
end
end
private
def ticket_params
params.require(:ticket).permit(:category, :deadline, :status, message_attributes: [:body])
end
答案 0 :(得分:1)
首先,您需要纠正关联。
同时拥有has_one :message
和has_many :messages
只会使人感到困惑,并且很可能无法按照您的预期方式工作。
特别需要注意的是:
belongs_to :ticket, inverse_of: :message
belongs_to :ticket, inverse_of: :messages
您认为这段代码做什么?如果您猜测它会创建两个关联,那么您错了。如果您有两个同名的关联,则后面的关联会覆盖前一个。
我建议您砍掉has_one
关联:
class Ticket < ApplicationRecord
has_many :messages
has_many :users, through: :messages
accepts_nested_attributes_for :messages
end
class Message < ApplicationRecord
belongs_to :user
belongs_to :ticket
validates_presence_of :user, :ticket
end
如果以后您想为最新消息(或第一条消息)添加单独的关联以进行急切加载,则需要将外键列放在票证表上并使用belongs_to
。
class Ticket < ApplicationRecord
belongs_to :latest_message
has_many :messages, after_add: :update_latest_message!
has_many :users, through: :messages
accepts_nested_attributes_for :messages
private
def update_latest_message!(msg)
self.update!(latest_message: msg)
end
end
然而,只有当您有大量邮件并且需要能够只加载最新消息时,这种优化才有意义。我将其留待以后使用。 过早的优化是万恶之源。
关于代码当前失败的原因,您应该看一下参数:
{ "utf8"=>"✓", ...
"ticket"=>{
"category"=>"Miscellaneous - Project",
"deadline"=>"2019-01-13",
"message"=>{"body"=>"sdf"}}, # should be messages_attributes
"button"=>""
}
}
您需要将表单设置为:
<%= form.fields_for :messages do |message_form| %>
<div class="form-group row">
<div class="col-sm-12">
<%= message_form.label :body %>
<%= message_form.text_area :body, class: "form-control" %>
</div>
</div>
<% end %>
并将其植入控制器:
def new
@ticket = Ticket.new
@ticket.messages.new # seed the form
end
即使用户一次只创建一条消息,您仍然希望使用消息关联。