rails 上使用 Action Cable ruby 的实时消息错误
error on Real time messages with Action Cable ruby on rails
我正在构建将保存到 sqlite 的文本消息系统,我收到的错误来自代码。在创建新消息时出现此错误
ActiveRecord::StatementInvalid (SQLite3::BusyException: database is locked: INSERT INTO "notifications" ("content", "user_id", "created_at", "updated_at") VALUES (?, ?, ?, ?)):
ActiveRecord::StatementInvalid (SQLite3::BusyException: database is locked: commit transaction):
如果我删除这一行
ActionCable.server.broadcast "conversation_#{@conversation.id}", message: render_message(@message)
来自 app/controllers/messages_controller.rb
class MessagesController < ApplicationController
before_action :authenticate_user!
before_action :set_conversation
def index
if current_user == @conversation.sender || current_user == @conversation.recipient
@other = current_user == @conversation.sender ? @conversation.recipient : @conversation.sender
@messages = @conversation.messages.order("created_at DESC")
else
redirect_to conversations_path, alert: "You don't have permission to view this."
end
end
def create
@message = @conversation.messages.new(message_params)
@messages = @conversation.messages.order("created_at DESC")
if @message.save
ActionCable.server.broadcast "conversation_#{@conversation.id}", message: render_message(@message)
redirect_to conversation_messages_path(@conversation)
end
end
private
def render_message(message)
self.render(partial: 'messages/message', locals: {message: message})
end
def set_conversation
@conversation = Conversation.find(params[:conversation_id])
end
def message_params
params.require(:message).permit(:context, :user_id)
end
end
我需要删除这部分 ,remote: true 从这一行
<%= form_for [@conversation, @conversation.messages.new], remote: true do |f| %>
来自 app/views/messages/index.html.erb
<div class="panel-body">
<div class="container text-center">
<%= form_for [@conversation, @conversation.messages.new], remote: true do |f| %>
<div class="form-group">
<%= f.text_field :context, placeholder: "Add a personal message", class: "form-control" %>
</div>
<%= f.hidden_field :user_id, value: current_user.id %>
<div>
<%= f.submit "Send Message", class: "btn btn-normal" %>
</div>
<% end %>
</div>
</div>
如果我删除了前 2 行消息将有效并保存到数据库中,但我不会在接收方进行实时更新,这是我的代码的其他部分
app/assets/javascripts/channels/messages.咖啡
$(() ->
App.messages = App.cable.subscriptions.create {channel: 'MessagesChannel', id: $('#conversation_id').val() },
received: (data) ->
$('#new_message')[0].reset()
$('#chat').prepend data.message
)
app/channels/messages_channel.rb
class MessagesChannel < ApplicationCable::Channel
def subscribed
stream_from "conversation_#{params[:id]}"
end
end
最后这个app/views/conversations/index.html.erb
<div class="container">
<% @conversations.each do |conversation| %>
<% other = current_user == conversation.sender ? conversation.recipient : conversation.sender %>
<%= link_to conversation_messages_path(conversation) do %>
<div class="row conversation">
<% if conversation.messages.any? %>
<div class="col-md-2">
<%= image_tag avatar_url(other), class: "img-circle avatar-medium" %>
</div>
<div class="col-md-2">
<%= other.fullname %>
<%= conversation.messages.last.message_time %>
</div>
<div class="col-md-8">
<%= conversation.messages.last.context %>
</div>
<% end %>
</div>
<% end %>
<% end %>
</div>
这里是config/database.yml
default: &default
adapter: sqlite3
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 30 } %>
timeout: 30000
development:
<<: *default
database: db/development.sqlite3
test:
<<: *default
database: db/test.sqlite3
production:
<<: *default
database: db/production.sqlite3
Sqlite3 的并发支持很差,因此请将数据库切换到更强大的后端 MySQL 或 Postgres。
我正在构建将保存到 sqlite 的文本消息系统,我收到的错误来自代码。在创建新消息时出现此错误
ActiveRecord::StatementInvalid (SQLite3::BusyException: database is locked: INSERT INTO "notifications" ("content", "user_id", "created_at", "updated_at") VALUES (?, ?, ?, ?)):
ActiveRecord::StatementInvalid (SQLite3::BusyException: database is locked: commit transaction):
如果我删除这一行
ActionCable.server.broadcast "conversation_#{@conversation.id}", message: render_message(@message)
来自 app/controllers/messages_controller.rb
class MessagesController < ApplicationController
before_action :authenticate_user!
before_action :set_conversation
def index
if current_user == @conversation.sender || current_user == @conversation.recipient
@other = current_user == @conversation.sender ? @conversation.recipient : @conversation.sender
@messages = @conversation.messages.order("created_at DESC")
else
redirect_to conversations_path, alert: "You don't have permission to view this."
end
end
def create
@message = @conversation.messages.new(message_params)
@messages = @conversation.messages.order("created_at DESC")
if @message.save
ActionCable.server.broadcast "conversation_#{@conversation.id}", message: render_message(@message)
redirect_to conversation_messages_path(@conversation)
end
end
private
def render_message(message)
self.render(partial: 'messages/message', locals: {message: message})
end
def set_conversation
@conversation = Conversation.find(params[:conversation_id])
end
def message_params
params.require(:message).permit(:context, :user_id)
end
end
我需要删除这部分 ,remote: true 从这一行
<%= form_for [@conversation, @conversation.messages.new], remote: true do |f| %>
来自 app/views/messages/index.html.erb
<div class="panel-body">
<div class="container text-center">
<%= form_for [@conversation, @conversation.messages.new], remote: true do |f| %>
<div class="form-group">
<%= f.text_field :context, placeholder: "Add a personal message", class: "form-control" %>
</div>
<%= f.hidden_field :user_id, value: current_user.id %>
<div>
<%= f.submit "Send Message", class: "btn btn-normal" %>
</div>
<% end %>
</div>
</div>
如果我删除了前 2 行消息将有效并保存到数据库中,但我不会在接收方进行实时更新,这是我的代码的其他部分
app/assets/javascripts/channels/messages.咖啡
$(() ->
App.messages = App.cable.subscriptions.create {channel: 'MessagesChannel', id: $('#conversation_id').val() },
received: (data) ->
$('#new_message')[0].reset()
$('#chat').prepend data.message
)
app/channels/messages_channel.rb
class MessagesChannel < ApplicationCable::Channel
def subscribed
stream_from "conversation_#{params[:id]}"
end
end
最后这个app/views/conversations/index.html.erb
<div class="container">
<% @conversations.each do |conversation| %>
<% other = current_user == conversation.sender ? conversation.recipient : conversation.sender %>
<%= link_to conversation_messages_path(conversation) do %>
<div class="row conversation">
<% if conversation.messages.any? %>
<div class="col-md-2">
<%= image_tag avatar_url(other), class: "img-circle avatar-medium" %>
</div>
<div class="col-md-2">
<%= other.fullname %>
<%= conversation.messages.last.message_time %>
</div>
<div class="col-md-8">
<%= conversation.messages.last.context %>
</div>
<% end %>
</div>
<% end %>
<% end %>
</div>
这里是config/database.yml
default: &default
adapter: sqlite3
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 30 } %>
timeout: 30000
development:
<<: *default
database: db/development.sqlite3
test:
<<: *default
database: db/test.sqlite3
production:
<<: *default
database: db/production.sqlite3
Sqlite3 的并发支持很差,因此请将数据库切换到更强大的后端 MySQL 或 Postgres。