将数组添加到活动记录对象

时间:2014-10-07 13:54:08

标签: ruby-on-rails ruby activerecord rails-activerecord

假设我有Campaign#show action,如下所示:

 def show
   @campaign = Campaign.find(params[:id])
 end

假设,我希望在我的视图中显示我从YouTube API获得的一些信息,用变量编写,因此Campaign#show现在看起来像这样:

def show
  @campaign = Campaign.find(params[:id])
  @views = Campaign.youtube_info(@campaign.url) # this class method of Campaign
end

但为了方便起见,我想合并@campaign和@views,并在@campaign中使用@campaign [:views] [:view_count]。

据我所知@campaing是ActiveRecord对象,而@views是Hash,不允许进行此类合并。

在这种情况下,最好的方法是什么?

提前致谢。

1 个答案:

答案 0 :(得分:2)

首先,您将向视图传递任意数量的对象,作为普通Rails应用程序的一部分。使用@views@campaign完全没有错。

然而,在你的情况下,事情写得非常奇怪。

首先,views应该是Campaign上的方法,它应该只调用youtube_info

奇怪的是youtube_info是类级方法,因为它需要从类的实例输入属性。它应该是一个实例方法,您只需在视图中调用该方法即可。

如果要阻止对每次调用的API进行额外调用,请缓存第一次调用的结果。 “缓存”方法的返回值的过程称为 memoization ,您可以在Ruby世界中找到很多关于它的文章。以下是Ruby中的常见模式:

class Campaign < ActiveRecord::Base
  def youtube_info
    @youtube_info ||= perform_some_api_request(@url)
  end

  def views
    youtube_info['views']
  end
end

方法youtube_info仅在首次运行时调用perform_some_api_request方法。结果将分配给@youtube_info,然后返回。每个后续调用都将测试@youtube_info,如果将其设置为非虚假值,则返回它。每次调用views都只会调用youtube_info,只有第一次调用才会执行API调用。

你可以使用相同的技术,并保持你的代码完全按照书面形式,改为调用类级方法,但我不推荐它:

class Campaign < ActiveRecord::Base
  def self.youtube_info(url)
    # ...
  end

  def views
    @views ||= Campaign.youtube_info(@url)['views']
  end
end

但是,第一个例子更好。 youtube_info没有理由成为类级方法。