ActionCable 在操作后显示一个空白页面
ActionCable displays an empty page after action
我正在关注 Michael Hartl tutorial 关于 Rails 5 ActionCable,以建立一个简单的聊天,但我在 MessageController
中的 create
操作中出现了问题:
def create
message = current_user.messages.build(message_params)
if message.save
ActionCable.server.broadcast 'room_channel',
content: message.content,
username: message.user.username
head :ok
end
end
它一直持续到 head :ok
,然后显示一个空的 HTML 页面。日志是:
Processing by MessagesController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"h9UsB78aX8mO8Nyn8eZEUuDzAOxL4V7UCMwNuTfwALliMv7OCkcUIeR4/xXIcvPjwq9H1bphjn6G96G+0VYisw==", "message"=>{"content"=>"oi"}, "commit"=>"Send"}
User Load (1.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
Message Load (2.1ms) SELECT "messages".* FROM "messages" ORDER BY "messages"."created_at" DESC LIMIT ? [["LIMIT", 50]]
(0.3ms) begin transaction
SQL (9.3ms) INSERT INTO "messages" ("content", "user_id", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["content", "oi"], ["user_id", 1], ["created_at", 2016-09-19 02:12:58 UTC], ["updated_at", 2016-09-19 02:12:58 UTC]]
(9.1ms) commit transaction
[ActionCable] Broadcasting to room_channel: {:content=>"oi", :username=>"alice"}
Completed 200 OK in 69ms (ActiveRecord: 22.0ms)
RoomChannel transmitting {"content"=>"oi", "username"=>"alice"} (via streamed from room_channel)
Finished "/cable/" [WebSocket] for 10.0.2.2 at 2016-09-19 02:12:58 +0000
RoomChannel stopped streaming from room_channel
(之后刷新页面,消息正常显示)
为什么会这样?
我的房间频道class:
class RoomChannel < ApplicationCable::Channel
def subscribed
stream_from "room_channel"
end
def unsubscribed
# Any cleanup needed when channel is unsubscribed
end
end
我的room.coffee
App.room = App.cable.subscriptions.create "RoomChannel",
connected: ->
# Called when the subscription is ready for use on the server
disconnected: ->
# Called when the subscription has been terminated by the server
received: (data) ->
alert data.content
根据建议,我将我为解决此问题所做的工作添加为答案。它没有回答为什么会发生这种情况,而是解决了问题。
解决方法是:移除head :ok
。
显然这是不必要的,因为如果我在操作中添加一个测试 whit assert_response :success
,它就会通过。
我知道答案已经被接受了,但这个解决方案对我来说很有效,无需删除 head :ok
,也许它可以帮助别人。
通常在开发环境中,人们 运行 localhost:3000
但我 运行 在不同的端口,localhost:3030
。
在这种情况下,我必须为该端口添加一个允许的请求来源,如下所示:
config.action_cable.allowed_request_origins = [
'http://localhost:3030'
]
给我的 /config/environments/development.rb
我正在学习 Michael 的 ActionCable 教程,但遇到了同样的问题。
我认为这是由于格式部分 _anything.html.erb
.
app/views/messages/_message_form.html
在学习本教程时,您将升级到 Action Cable 功能。但是在_message_form
部分,还是和通常的HTTP request
一样。因此,在您使用 messages_controller.rb
广播消息后,浏览器呈现一个空页面,因为表单已经呈现。
app/views/messages/_message_form.html
, 原:
<div class="message-input">
<%= form_for(@message) do |f| %>
<%= f.text_area :content %>
<%= f.submit "Send" %>
<% end %>
</div>
因此,您必须将 remote: true
添加到表单中,如下所示:
<div class="message-input">
<%= form_for(@message, remote: true) do |f| %>
<%= f.text_area :content %>
<%= f.submit "Send" %>
<% end %>
</div>
添加 remote: true
发出 JS 请求(Ajax,在本例中)
引用迈克尔的话:
You can verify by submitting a message that it appears as desired, but in
fact this is a cheat because the form from Listing 6 is currently submitting
an ordinary HTTP POST
request, which causes the page to refresh. In order
to use Action Cable, we need to change the form to submit a remote request
that submits an Ajax request without refreshing the page. We can do this by
including the remote: true
option in the call to form_for
.
请注意,我所做的一切都是在 localhost:3000
我正在关注 Michael Hartl tutorial 关于 Rails 5 ActionCable,以建立一个简单的聊天,但我在 MessageController
中的 create
操作中出现了问题:
def create
message = current_user.messages.build(message_params)
if message.save
ActionCable.server.broadcast 'room_channel',
content: message.content,
username: message.user.username
head :ok
end
end
它一直持续到 head :ok
,然后显示一个空的 HTML 页面。日志是:
Processing by MessagesController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"h9UsB78aX8mO8Nyn8eZEUuDzAOxL4V7UCMwNuTfwALliMv7OCkcUIeR4/xXIcvPjwq9H1bphjn6G96G+0VYisw==", "message"=>{"content"=>"oi"}, "commit"=>"Send"}
User Load (1.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
Message Load (2.1ms) SELECT "messages".* FROM "messages" ORDER BY "messages"."created_at" DESC LIMIT ? [["LIMIT", 50]]
(0.3ms) begin transaction
SQL (9.3ms) INSERT INTO "messages" ("content", "user_id", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["content", "oi"], ["user_id", 1], ["created_at", 2016-09-19 02:12:58 UTC], ["updated_at", 2016-09-19 02:12:58 UTC]]
(9.1ms) commit transaction
[ActionCable] Broadcasting to room_channel: {:content=>"oi", :username=>"alice"}
Completed 200 OK in 69ms (ActiveRecord: 22.0ms)
RoomChannel transmitting {"content"=>"oi", "username"=>"alice"} (via streamed from room_channel)
Finished "/cable/" [WebSocket] for 10.0.2.2 at 2016-09-19 02:12:58 +0000
RoomChannel stopped streaming from room_channel
(之后刷新页面,消息正常显示)
为什么会这样?
我的房间频道class:
class RoomChannel < ApplicationCable::Channel
def subscribed
stream_from "room_channel"
end
def unsubscribed
# Any cleanup needed when channel is unsubscribed
end
end
我的room.coffee
App.room = App.cable.subscriptions.create "RoomChannel",
connected: ->
# Called when the subscription is ready for use on the server
disconnected: ->
# Called when the subscription has been terminated by the server
received: (data) ->
alert data.content
根据建议,我将我为解决此问题所做的工作添加为答案。它没有回答为什么会发生这种情况,而是解决了问题。
解决方法是:移除head :ok
。
显然这是不必要的,因为如果我在操作中添加一个测试 whit assert_response :success
,它就会通过。
我知道答案已经被接受了,但这个解决方案对我来说很有效,无需删除 head :ok
,也许它可以帮助别人。
通常在开发环境中,人们 运行 localhost:3000
但我 运行 在不同的端口,localhost:3030
。
在这种情况下,我必须为该端口添加一个允许的请求来源,如下所示:
config.action_cable.allowed_request_origins = [
'http://localhost:3030'
]
给我的 /config/environments/development.rb
我正在学习 Michael 的 ActionCable 教程,但遇到了同样的问题。
我认为这是由于格式部分 _anything.html.erb
.
app/views/messages/_message_form.html
在学习本教程时,您将升级到 Action Cable 功能。但是在_message_form
部分,还是和通常的HTTP request
一样。因此,在您使用 messages_controller.rb
广播消息后,浏览器呈现一个空页面,因为表单已经呈现。
app/views/messages/_message_form.html
, 原:
<div class="message-input">
<%= form_for(@message) do |f| %>
<%= f.text_area :content %>
<%= f.submit "Send" %>
<% end %>
</div>
因此,您必须将 remote: true
添加到表单中,如下所示:
<div class="message-input">
<%= form_for(@message, remote: true) do |f| %>
<%= f.text_area :content %>
<%= f.submit "Send" %>
<% end %>
</div>
添加 remote: true
发出 JS 请求(Ajax,在本例中)
引用迈克尔的话:
You can verify by submitting a message that it appears as desired, but in fact this is a cheat because the form from Listing 6 is currently submitting an ordinary
HTTP POST
request, which causes the page to refresh. In order to use Action Cable, we need to change the form to submit a remote request that submits an Ajax request without refreshing the page. We can do this by including theremote: true
option in the call toform_for
.
请注意,我所做的一切都是在 localhost:3000