描述
我正在嘗試messages基于usersRuby on Rails 瀏覽器中的選定(通過復選框)進行創建。
快照:

重現步驟
- 我的架構
ActiveRecord::Schema.define(version: 2021_11_13_142255) do
create_table "messages", force: :cascade do |t|
t.text "content"
t.integer "user_id"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
end
create_table "users", force: :cascade do |t|
t.string "name"
t.string "role"
t.integer "phone"
t.boolean "admin"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
end
end
- 訊息控制器.rb
class MessagesController < ApplicationController
def new
@users = User.all
@message = Message.new(message_params)
end
def create
params[:user_objs].each do |u|
# "params.inspect" returns
# {"authenticity_token"=>"[FILTERED]",
# "user_objs"=>
# ["{\"id\":1,\"name\":\"Alex\",\"role\":\"Engineer\",\"phone\":998943333303,\"admin\":true,\"created_at\":\"2021-11-13T14:37:54.962Z\",\"updated_at\":\"2021-11-13T14:37:54.962Z\"}",
# "{\"id\":2,\"name\":\"Lucy\",\"role\":\"Accountant\",\"phone\":998943333303,\"admin\":false,\"created_at\":\"2021-11-13T14:39:52.742Z\",\"updated_at\":\"2021-11-13T14:39:52.742Z\"}"],
# "message"=>{"content"=>"Message from the browser"},
# "commit"=>"Send"}
person = JSON.parse(u)
@message = person.messages.new(message_params)
if @message.save
redirect_to root_path
else
@users = User.all
render :new
end
end
end
private
def message_params
params.permit(
:content,
:user_id
)
end
end
- 訊息 => new.html.erb
<div>
<h1>Create and send a new message!</h1>
<%= form_for(@message) do |form| %>
<% if @message.errors.any? %>
<div class="alert alert-danger">
<h5 class="fw-bold">Invalid input!</h5>
<%= @message.errors.full_messages.each do |error| %>
<div><%= error %></div>
<% end %>
</div>
<% end %>
<% @users.each do |u| %>
<div>
<p><%= check_box_tag "user_objs[]", u.to_json %> <%= u.name %></p>
</div>
<% end %>
<p class="mb-3">
<%= form.label :content, class: "form-label" %>
<%= form.text_field :content, class: "form-control", autofocus: true, placeholder: "John_D" %>
</p>
<p class="mb-3">
<%= form.submit "Send", class: "btn btn-primary" %>
</p>
<% end %>
</div>
<%= params.inspect %>
- 楷模
# user.rb
class User < ApplicationRecord
has_many :messages
end
# message.rb
class Message < ApplicationRecord
belongs_to :user
end
預期行為
我期待為所有選定的用戶創建訊息
實際行為
NoMethodError in MessagesController#create
undefined method `messages' for #<Hash:0x000000011fe2b420>
我嘗試了不同的方法,但無法將 Ruby 物件轉換為JSON我的,params user_objs[]以便我可以在我的控制器中決議它以根據user_objs[]引數中的那些選定用戶創建訊息。
環境資訊
ruby -v
ruby 2.7.3p183 (2021-04-05 revision 6847ee089d) [arm64-darwin20]
rails -v
Rails 6.1.4.1
感謝您提供的任何幫助??
uj5u.com熱心網友回復:
如果要創建一個向多個用戶發送一條訊息的系統,您可以設定一個連接表:
class User < ApplicationRecord
has_many :user_messages
has_many :recieved_messages, though: :user_messages,
source: :message,
inverse_of: :recipients
end
# rails g model user_message user:belongs_to message:belongs_to read:boolean
class UserMessage < ApplicationRecord
belongs_to :user
belongs_to :message
# make sure to add a compound unique index to the migration as well
validates_uniqueness_of :user_id, scope: :message_id
delegate :content, to: :message
end
class Message < ApplicationRecord
has_many :user_messages
has_many :recipients, though: :user_messages,
source: :user,
inverse_of: :recieved_messages
end
has_many :recipients將創建一個可以在表單中使用的recipient_ids=setter 和recipient_idsgetter:
<div>
<h1>Create and send a new message!</h1>
<%= form_with(model: @message) do |form| %>
<% if @message.errors.any? %>
<div class="alert alert-danger">
<h5 class="fw-bold">Invalid input!</h5>
<%= @message.errors.full_messages.each do |error| %>
<div><%= error %></div>
<% end %>
</div>
<% end %>
<p class="mb-3">
<%= form.collection_checkboxes(:recipient_ids, @users, :id, :name) %>
</p>
<p class="mb-3">
<%= form.label :content, class: "form-label" %>
<%= form.text_field :content, class: "form-control", autofocus: true, placeholder: "John_D" %>
</p>
<p class="mb-3">
<%= form.submit "Send", class: "btn btn-primary" %>
</p>
<% end %>
</div>
絕對不需要將整個記錄作為 JSON 傳遞——您只需傳遞一個 ID 陣列,rails 將為您完成創建連接表行的所有作業:
class MessagesController < ApplicationController
def new
@users = User.all
@message = Message.new
end
def create
@message = Message.new(message_params)
if @message.save
redirect_to root_path
else
@users = User.all
render :new
end
end
private
def message_params
params.require(:message)
.permit(
:content,
recipient_ids: []
)
end
end
這避免了從單個請求創建多個記錄的復雜性以及將表單系結到單個 Message 實體但創建一堆必然會導致混淆的記錄的整個難題。
如果您想一次創建多個記錄,它可以完成,但復雜性要高得多,并且您必須處理諸如在創建一條訊息失敗時如何處理錯誤之類的事情,這可能超出您當前的技能水平。
uj5u.com熱心網友回復:
問題是您在person = JSON.parse(u). 這不是活動記錄,因此在執行person.messages此操作時會引發錯誤。我相信您在創建操作中需要的是:
user = JSON.parse(u)
# make sure user.inspect gives you the user object you want
person = User.find(user["id"])
# person.inspect should give you the active record for the user
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/358368.html
下一篇:在Rails中包含模塊
