【问题标题】:Ruby instance variable across classes or a better way to share an object among classes within an instance跨类的 Ruby 实例变量或在实例内的类之间共享对象的更好方法
【发布时间】:2015-03-28 01:07:55
【问题描述】:

我正在使用 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 是@ 的实例987654330@ 并且没有引用 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,它没有使用正确的。

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

【问题讨论】:

  • 我正在尝试使用 gem。它不是我创建的,我在使用它时遇到了问题,因为我的应用程序是多用户的,并且 oauth_token 是在模块/类级别设置的,并且似乎适用于所有实例。

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


【解决方案1】:

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

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

你介意把讨论移到那里吗?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-28
    相关资源
    最近更新 更多