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

时间:2015-03-26 20:30:50

标签: ruby-on-rails ruby instance-variables multiple-instances

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

可以按预期初始化Client类,并且可以为实例(Mavenlink::Client.new(oauth_token: "12345")提供oauth令牌,并且通过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作为workspace的对象是Workspace < 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(所有资源的父类,例如Workspace): 这是最终发出请求的方法

# @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_tokens,则不会使用正确的用户。

非常感谢任何帮助或指导。我可能没有为任何人提供足够的解释来解决这个问题,但让我知道我可以发布的其他信息。谢谢!

1 个答案:

答案 0 :(得分:0)

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

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

你介意在那里讨论吗?