【问题标题】:Combine API data with local data in Rails在 Rails 中结合 API 数据和本地数据
【发布时间】:2012-11-16 21:09:19
【问题描述】:

我正在我的 Rails 3 应用程序中使用 GoCardless API。我有一个订阅模型,它有一个与远程记录的 id 匹配的 resource_id 列。

我正在尝试从 API 获取本地订阅记录的额外信息。

订阅索引视图

<% @subscriptions.each do |subscription| %>
  <tr>
    <td><%= subscription.resource_id %></td>
    <td><%= subscription.resource_type %></td>
    <td><%= subscription.signature %></td>
    <td><%= subscription.state %></td>
    <td><%= @gocardless.next_interval_start %></td>
    <td><%= link_to 'Show', subscription %></td>
    <td><%= link_to 'Edit', edit_subscription_path(subscription) %></td>
    <td><%= link_to 'Destroy', subscription, method: :delete, data: { confirm: 'Are you sure?' } %></td>
  </tr>
<% end %>

订阅控制器

def index
 @subscriptions = Subscription.all
 @gocardless = GoCardless::Merchant.find("XXXXXXXXXX").subscriptions

 respond_to do |format|
   format.html # index.html.erb
   format.json { render json: @subscriptions }
 end
end

如您所见,我正在使用以下行来检索下一个间隔开始日期

<%= @gocardless.next_interval_start %>

这不起作用并返回 nil。但是,如果我将其更改为以下所有记录,则会显示来自 API 的第一条记录的值。

<%= @gocardless.first.next_interval_start %>

根据 GoCardless API documentation,您可以使用以下方式查找订阅:

GoCardless::Subscription.find("XXXXXXXXXX")  # =>  #<GoCardless::Subscription ...>

所以,我的问题。如何将当前订阅 resource_id 传递给 API,以便查看每个本地订阅记录的 next_internal_start 值?

更新

使用下面的 Adam 示例,我从 GoCardless 收到 404 响应。我认为这是由于我没有在请求中设置商家 ID。当我将方法更改为:

def gc_subscription
  @gc_subscription ||= GoCardless::Merchant.find("MERCHANTID").subscriptions.find(self.resource_id)
end

对于我尝试使用以下代码请求的任何属性,我得到undefined methodinterval' for #`:

<% for subscription in @subscriptions %>
 <%= subscription.gc_subscription.amount
<% end %>

当使用相同的代码获取本地内容时,它会按预期工作:

<% for subscription in @subscriptions %>
 <%= subscription.resource_id %>
<% end %>

我已检查我尝试检索的值在 API 中是否可用。 https://sandbox.gocardless.com/docs/api_guide#resources-available

更新二

与调用第一个结果之前一样,使用 Adam 的方法:

<%= subscription.gc_subscription.first.amount %>

这将返回 2.5,这是第一个订阅的值。

【问题讨论】:

    标签: ruby-on-rails-3 api controller record


    【解决方案1】:

    如果我有一个链接到远程数据源的本地订阅模型,我的订阅模型上会有一个类似的方法,它提供对远程对象的访问:

    def gc_subscription
      @gc_subscription ||= GoCardless::Subscription.find(self.resource_id)
    end
    

    然后您可以根据需要访问此方法,而无需视图或控制器中的任何 GC 逻辑。例如:

    for subscription in @subscriptions
       subscription.gc_subscription.some_method #=> "output"
    end
    

    或者,如果您只使用一个订阅:

    subscription = Subscription.find(id)
    subscription                 #=> Your local Subscription instance
    subscription.gc_subscription #=> GoCardless::Subscription instance
    

    这样配置后,您将能够从控制器中删除 @gocardless 并将您的视图替换为:

    <% @subscriptions.each do |subscription| %>
      <tr>
        <td><%= subscription.resource_id %></td>
        <td><%= subscription.resource_type %></td>
        <td><%= subscription.signature %></td>
        <td><%= subscription.state %></td>
        <td><%= subscription.gc_subscription.next_interval_start %></td>
        <td><%= link_to 'Show', subscription %></td>
        <td><%= link_to 'Edit', edit_subscription_path(subscription) %></td>
        <td><%= link_to 'Destroy', subscription, method: :delete, data: { confirm: 'Are you sure?' } %></td>
      </tr>
    <% end %>
    

    希望对你有帮助。

    【讨论】:

    • 我只想补充一点,如果订阅量很大,这会很慢。更高效的是通过对 API 的单个请求来检索所有数据。
    • 谢谢亚当。我还是有点困惑。我已将该方法添加到订阅模型中,并从控制器中删除了 GC 逻辑。在索引视图中我有&lt;% @subscriptions.each do |subscription| %&gt;,然后调用&lt;%= subscription.gc_subscription.next_interval_start %&gt;。我得到一个 404 错误。我检查了订阅表只有一个有效的 resource_id。我应该在控制器中有subscription = Subscription.find(id) 吗?
    • 我认为可能是 404,因为我没有设置我的商家 ID。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多