【发布时间】:2021-07-03 20:20:33
【问题描述】:
我有一个 Rails api,我正在尝试为 git gui 创建一个实时流功能。我有一个控制器和一个用于提交更新的通道,我想在通道的订阅操作中使用实时流功能。这可能吗?或者有没有更好的 Rails 方法来做到这一点。我认为正确的方法是在我的控制器方法中使用ActionCable.server.broadcast('commit_updates', { body: return_data }),但我没有在任何地方调用我的控制器方法。我在哪里/如何调用它,以便它在订阅它的客户端上运行?还是应该将逻辑放在通道内?
这是我的 commit_updates_controller.rb
class CommitUpdatesController < ApplicationController
include ActionController::Live
require 'listen'
require 'json'
$file_path = "#{Dir.getwd}/.git/objects"
@@commits = {}
@@commits_array = []
@@edges_array = []
def index
end
def live_stream
# get folders exlcluding ".","..", "pack","info"
folders = Dir.entries($file_path).select {|folder| /^[a-z0-9]{2}$/i.match(folder) }
folders.each do |folder|
files = Dir.children("#{$file_path}/#{folder}")
files.each do |file|
CommitUpdate.find_commit_info(folder, file, @@commits_array)
end
end
generate_edges
ActionCable.server.broadcast('commit_updates', { body: return_data })
p return_data
# listens to any changes that happen to the git folder while the program is open
listener = Listen.to($file_path) do |modified, added, removed|
# puts(modified: modified, added: added, removed: removed)
added.each do |new_file_path|
split_new_file_path = new_file_path.split("/").reject!{|item| item.empty?}
folder = split_new_file_path[split_new_file_path.length() - 2]
file = split_new_file_path[split_new_file_path.length - 1]
CommitUpdate.find_commit_info(folder, file, @@commits_array)
add_edge(@@edges_array, CommitUpdate.get_commit_info(folder, file))
ActionCable.server.broadcast('commit_updates', { body: return_data })
end
end
listener.start
sleep
end
private
def generate_edges
if @@commits_array.length != 0
@@commits_array.each do |commit|
add_edge(@@commits_array, commit)
end
end
end
def add_edge(array, commit)
if commit[:parents] != []
commit[:parents].each {|parent| @@edges_array.push({from: parent, to: commit[:sha1]})}
end
end
def return_data
ret = {
:nodes => @@commits_array,
:links => @@edges_array
}
return ret.to_json
end
end
这是我的 commit_updates_channel.rb
class CommitUpdatesChannel < ApplicationCable::Channel
def subscribed
stream_from 'commit_updates'
end
end
这是我的 commit_updates.rb 模型
class CommitUpdate < ApplicationRecord
def self.find_commit_info(folder, file, array)
file_type = self.check_sha1_type(folder, file)
if file_type == "commit"
array.push(
self.get_commit_info(folder, file)
)
end
end
def self.get_commit_info(folder, file)
author = ""
parents = []
commit_message = ""
unixtime = ""
decoded_file = `git cat-file -p #{folder}#{file}`
file_data_array = decoded_file.split("\n").reject!{|item| item.empty?}
p file_data_array
file_data_array.each do |item|
split_item = item.split(" ")
case split_item[0]
when "author"
author = split_item[1..split_item.length() - 4].join(" ")
when "parent"
parents.push(split_item[1])
when "tree"
next
when "blob"
next
when "committer"
unixtime = split_item[split_item.length - 2]
else
commit_message = split_item.join(" ")
end
end
commit_info = {
:sha1 => "#{folder}#{file}",
:parents => parents,
:commit_message => commit_message,
:author => author,
:unixtime => unixtime,
:id => "#{folder}#{file}",
:label => "#{folder}#{file[0..4]}...",
:font => "18px verdana blue",
}
return commit_info
end
private
def self.check_sha1_type(folder, file)
return `git cat-file -t #{folder}#{file}`.chomp
end
end
【问题讨论】:
标签: ruby websocket ruby-on-rails-6 actioncable