跨类的Ruby实例变量,或者在实例中的类之间共享对象的更好方法



我正在使用一个API gem mavenlik_gem,它不能很好地处理多个用户。它使用oauth令牌进行授权,但似乎因为这是在类级别而不是实例级别定义的,所以访问应用程序的多个用户最终都会使用相同的令牌(第一次使用时的令牌)。

Client类可以按预期初始化,并且可以为实例提供oauth令牌(Mavenlink::Client.new(oauth_token: "12345"),并且通过接受客户端对象的Mavenlink::Request类向API发出请求,或者如果没有提供,则创建新对象(这是问题的一部分)。

示例:

client = Mavenlink::Client.new(oauth_token: "12345") // OK
workspace = client.workspaces.find(1) // OK
participants = workspace.participants // Fails because calling the association intantiates a new Mavenlink::Request and does not pass it the `client`

当我在资源上调用save(本例中为workspace)时,它会创建Mavenlink::Request的新实例,并且不会传入client对象,因为workspaceWorkspace < Model的实例,并且没有引用client实例。

无论如何,也许代码可以比我更好地解释它。。。。

client.rb:

module Mavenlink
  class Client
    ENDPOINT = 'https://api.mavenlink.com/api/v1/'.freeze
    # @param settings [ActiveSuppport::HashWithIndifferentAccess]
    def initialize(settings = Mavenlink.default_settings)
      @settings = settings
      # @oauth_token = settings[:oauth_token] or raise ArgumentError, 'OAuth token is not set'
      @oauth_token = Mavenlink.oauth_token or raise ArgumentError, 'OAuth token is not set'
      # TODO: implement with method_missing?
      # Declare API calls client.-->>workspaces<<---.create({})
      Mavenlink.specification.keys.each do |collection_name|
        singleton_class.instance_eval do
          define_method collection_name do
            ::Mavenlink::Request.new(collection_name, self)
          end
        end
      end
    end
...

request.rb:

module Mavenlink
  class Request
    include Enumerable
    attr_reader :client, :collection_name
    attr_accessor :scope
    # @param collection_name [String, Symbol]
    # @param client [Mavenlink::Client]
    def initialize(collection_name, client = Mavenlink::Client.new)
      @collection_name = collection_name
      @client = client
      @scope = ActiveSupport::HashWithIndifferentAccess.new
    end
...

model.rb(所有资源的父类,如"工作区"):这是最终使请求的方法

# @return [Mavenlink::Request]
def self.scoped
  Mavenlink::Request.new(collection_name) // At this point, I need to pass in client/@client/oauth_token or something...
end

因此,我的一个相当长的问题围绕着我是否可以在多个类中拥有一个实例变量(@client)。或者如何最好地将@client放入Model类,因为请求不是来自client

以下是错误跟踪:

1.9.3-p484 :001 > client = Mavenlink::Client.new(oauth_token: "12345")
 => #<Mavenlink::Client:0x007fab5bacc4a8 @settings={:oauth_token=>"12345"}, @oauth_token="12345"> 
1.9.3-p484 :002 > workspace = client.workspaces.first
I, [2015-03-26T13:18:41.170598 #89994]  INFO -- : [Maven] Started GET /workspaces with {}
 => {"title"=>"Jira Project II", "archived"=>false, "description"=>"", "due_date"=>"", "effective_due_date"=>"", "start_date"=>"", "budgeted"=>true, "change_orders_enabled"=>true, "updated_at"=>"2015-03-26T08:21:08-07:00", "created_at"=>"2015-02-18T09:55:53-08:00", "consultant_role_name"=>"Consultants", "client_role_name"=>"Clients", "percentage_complete"=>1, "access_level"=>"invitation", "exclude_archived_stories_percent_complete"=>false, "can_create_line_items"=>true, "default_rate"=>nil, "currency_symbol"=>"$", "currency_base_unit"=>100, "can_invite"=>true, "has_budget_access"=>true, "tasks_default_non_billable"=>false, "rate_card_id"=>nil, "workspace_invoice_preference_id"=>nil, "posts_require_privacy_decision"=>false, "require_time_approvals"=>false, "require_expense_approvals"=>false, "price"=>"TBD", "price_in_cents"=>nil, "budget_used"=>"$0", "over_budget"=>false, "currency"=>"USD", "expenses_in_burn_rate"=>true, "status"=>{"color"=>"green", "message"=>"Active"}, "permissions"=>{"can_upload_files"=>true, "can_private_message"=>true, "can_join"=>false, "is_participant"=>true, "access_level"=>"team_lead", "user_is_client"=>false}, "id"=>"7232855", "creator_id"=>"5207615"} 
1.9.3-p484 :003 > workspace.participants
ArgumentError: OAuth token is not set
    from /Users/Adam/Mavenlink/mavenlink_gem/lib/mavenlink/client.rb:8:in `initialize'
    from /Users/Adam/Mavenlink/mavenlink_gem/lib/mavenlink.rb:27:in `new'
    from /Users/Adam/Mavenlink/mavenlink_gem/lib/mavenlink.rb:27:in `client'
    from /Users/Adam/Mavenlink/mavenlink_gem/lib/mavenlink/request.rb:10:in `initialize'
    from /Users/Adam/Mavenlink/mavenlink_gem/lib/mavenlink/model.rb:36:in `new'
    from /Users/Adam/Mavenlink/mavenlink_gem/lib/mavenlink/model.rb:36:in `scoped'
    from /Users/Adam/Mavenlink/mavenlink_gem/lib/mavenlink/model.rb:221:in `request'
    from /Users/Adam/Mavenlink/mavenlink_gem/lib/mavenlink/model.rb:245:in `reload_association'
    from /Users/Adam/Mavenlink/mavenlink_gem/lib/mavenlink/model.rb:71:in `block in association'
    from (irb):3
    from /Users/Adam/Mavenlink/mavenlink_gem/bin/mavenlink-console:18:in `<top (required)>'
    from /Users/Adam/.rvm/gems/ruby-1.9.3-p484/bin/mavenlink-console:23:in `load'
    from /Users/Adam/.rvm/gems/ruby-1.9.3-p484/bin/mavenlink-console:23:in `<main>'
    from /Users/Adam/.rvm/gems/ruby-1.9.3-p484/bin/ruby_executable_hooks:15:in `eval'
    from /Users/Adam/.rvm/gems/ruby-1.9.3-p484/bin/ruby_executable_hooks:15:in `<main>'
1.9.3-p484 :004 > 

值得注意的是,oauth_token可以在Mavenlink模块中的模块级别进行设置,这样就解决了单个用户的问题,但我发现,当部署为多租户,多个用户登录,每个用户都有不同的oauth_token时,它没有使用正确的oauth_Token。

如有任何帮助或指导,我们将不胜感激。我可能没有为任何人提供足够的解释来解决这个问题,但让我知道我还可以发布什么其他信息。谢谢

我认为您发现了一个真正的错误。我将在gem的GitHub问题上发表一个问题,我们可以看看修复它。

https://github.com/mavenlink/mavenlink_gem/issues/17

你介意把讨论转移到那边吗?

最新更新