Gem rails2.3 vendor/plugins/ 下的 gem 该如何加载到 rack application 里面?

algo31031 · 2014年06月30日 · 最后由 algo31031 回复于 2014年07月03日 · 2985 次阅读

前段时间用 faye 为系统添加了即时聊天的功能,faye server 被打包进 rack application, 通过/config/initializers/faye.rb, 使用 thin 随 rails 一同启动。

之后客户追加新功能,需要对未在线用户,如果有新的聊天信息,要对其进行提醒

因为要兼顾 IE 用户,未使用 faye websocket. 所以判断用户是否在线采取的策略是:

  1. 在 rack 程序里添加 faye server 端扩展,遇到 subscribe event 则把对应 user 设为在线状态,同时记录下使用的 clientId
  2. 监听 unsubscribe 和 disconnect 事件,通过 clientId 找到该 user, 将其标记为离线

标记在线/离线时候,使用到了 ActiveRecord 的 model, 而 model 里又用到了位于 vendor/plugins/下的 gem, acts_as_paranoid. 于是在 rack 里面一顿 require, 总算是在本地能跑起来 (development 下的 thin/webrick, production 下 apache+passenger) 但是部署到服务器之后,发现 thin 启动不起来,报错说找不到destroy_without_callbacks方法

又折腾了好半天没什么结果,恳请大家帮我看下是哪儿出了问题,非常感谢。

thin 启动失败的报错信息

/home/college-dev/rails/vendor/plugins/acts_as_paranoid/lib/caboose/acts/paranoid.rb:56:in `alias_method': undefined method `destroy_without_callbacks' for class `UserChatTeam' (NameError)
    from /home/college-dev/rails/vendor/plugins/acts_as_paranoid/lib/caboose/acts/paranoid.rb:56:in `acts_as_paranoid'
    from /home/college-dev/rails/app/models/user_chat_team.rb:2
    from /usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require'
    from /usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `require'
    from /usr/lib/ruby/gems/1.8/gems/activesupport-3.1.3/lib/active_support/dependencies.rb:240:in `require'
    from /usr/lib/ruby/gems/1.8/gems/activesupport-3.1.3/lib/active_support/dependencies.rb:223:in `load_dependency'
    from /usr/lib/ruby/gems/1.8/gems/activesupport-3.1.3/lib/active_support/dependencies.rb:640:in `new_constants_in'
    from /usr/lib/ruby/gems/1.8/gems/activesupport-3.1.3/lib/active_support/dependencies.rb:223:in `load_dependency'
    from /usr/lib/ruby/gems/1.8/gems/activesupport-3.1.3/lib/active_support/dependencies.rb:240:in `require'
    from faye.ru:14
    from /usr/lib/ruby/gems/1.8/gems/rack-1.3.6/lib/rack/builder.rb:51:in `instance_eval'
    from /usr/lib/ruby/gems/1.8/gems/rack-1.3.6/lib/rack/builder.rb:51:in `initialize'
    from faye.ru:1:in `new'
    from faye.ru:1

faye.ru 的内容

require 'faye'
require File.expand_path('../config/initializers/faye_token.rb', __FILE__)
require 'active_record'
require 'mysql'
require 'yaml'

# using 'acts_as_paranoid' as a plugin in 'vendor/plugins'
RAILS_ENV = ENV['RACK_ENV'] 
load 'active_record/associations.rb' 
require File.expand_path('../vendor/plugins/acts_as_paranoid/lib/caboose/acts/paranoid.rb', __FILE__)
require File.expand_path('../vendor/plugins/acts_as_paranoid/lib/caboose/acts/belongs_to_with_deleted_association.rb', __FILE__)
require File.expand_path('../vendor/plugins/acts_as_paranoid/lib/caboose/acts/has_many_through_without_deleted_association.rb', __FILE__)
require File.expand_path('../vendor/plugins/acts_as_paranoid/init.rb', __FILE__)
require File.expand_path('../app/models/user_chat_team.rb', __FILE__)

environment = ENV['RACK_ENV'] || 'production'
dbconfig    = YAML.load(File.read('config/database.yml'))
ActiveRecord::Base.establish_connection(dbconfig[environment])

class ServerAuth
  def incoming(message, callback)

    if message['channel'] !~ %r{^/meta/}
      if message['ext']['auth_token'] != FAYE_TOKEN
        message['error'] = 'Invalid authentication token.'
      else
        message['ext'].delete('auth_token')
      end
    end

    callback.call(message)
  end
end

class  MarkOnline
  def incoming(message, callback)

    if message['channel'] == '/meta/subscribe'
      UserChatTeam.mark_online( message['data']['user_id'], 
                                message['data']['chat_team_id'],
                                message['clientId']) 
    end

    callback.call(message)
  end

end


faye_server = Faye::RackAdapter.new(:mount => '/faye', :timeout => 45)
faye_server.add_extension(ServerAuth.new)
faye_server.add_extension(MarkOnline.new)

faye_server.on('unsubscribe') do |client_id, channel|
  UserChatTeam.mark_offline(client_id)  
end

faye_server.on('disconnect') do |client_id|
  UserChatTeam.mark_offline(client_id)   
end

run faye_server

faye.rb 的内容

# 随rails一起启动faye server
Thread.new do
  system("thin -C #{RAILS_ROOT}/config/faye.ym l start")
end

require 'yaml'

# もしキーが存在しなかったら例外を投げる様にする。
FAYE_CONFIG = Hash.new{|hash, key| raise(IndexError, "no such key : [#{key}] !!")}
FAYE_CONFIG.merge!(YAML.load(File.open(RAILS_ROOT + '/config/faye.yml')))
FAYE_CONFIG.each do |k,v|
  if v.is_a?(Hash)
    v.replace(Hash.new{|hash,key| raise(IndexError, "no such a key in FAYE_CONFIG : #{key} !!")}.merge(v))
  end
end

# FAYE_CONFIGのキーが全てSymbolで指定してあるかチェック
# Symbol以外の値は不正なので、例外を出して起動を中止する。
def faye_config_valid?(hash)
  hash.each do |k,v|
    unless k.is_a?(Symbol)
      # Railsの仕様で、environment.rb で例外を出しても起動してしまうが、
      # gem の読み込みエラーのみ停止してくれるので、仕方なくそれを利用する。
      # 詳細は config/boot.rb を参照のこと。
      require '/config/faye.yml のキーは全てシンボルでなければいけません。'
    end

    case 
    when v.is_a?(Hash)   # Hashならば、再帰処理
      faye_config_valid?(v)
    when v.is_a?(String) # Stringならば、{RAILS_ROOT}を実際の値に書き換える.
      v.sub!(/\{RAILS_ROOT\}/, RAILS_ROOT)
    end
  end
end
faye_config_valid?(FAYE_CONFIG)

# Don't Comment out!!
FAYE_CONFIG.freeze

自己回来结贴吧,趟不过去只好暂且绕过去

标记上下线的策略不变,但是不再在 faye.ru 里直接调用 ActiveRecord controller 添加了 2 个 action, rack 里直接向 rails 发 request 了

uri = URI.parse("#{ ENV['RAILS_ENV'] == 'development' ? 'http://localhost:3000' : FAYE_HOST }/mypage/chat_team/mark_online")
http = Net::HTTP.new(uri.host, uri.port)
if ENV['RAILS_ENV'] != 'development' && FAYE_HOST =~ /^https/
  http.use_ssl = true 
  http.verify_mode = OpenSSL::SSL::VERIFY_NONE
end
request = Net::HTTP::Post.new(uri.request_uri)
request.set_form_data({ :user_id => message['data']['user_id'],
                        :chat_team_id => message['data']['chat_team_id'],
                        :client_id => message['clientId'],
                        :faye_foken => FAYE_TOKEN})
http.request(request)
2 楼 已删除
3 楼 已删除
需要 登录 后方可回复, 如果你还没有账号请 注册新账号