在与持久数据相同的列表中显示未显示的数据

时间:2017-11-30 04:11:51

标签: ruby-on-rails ruby activerecord

我有两个数据源:我的数据库和第三方API。第三方API是“真相来源”,但我希望用户能够从第三方API“标记”item,然后将其保留在我的数据库中。

我面临的挑战是在同一个列表中显示两组item,而不会过于复杂。这是一个例子:

  • 第1项(未加入书签,来自第三方API)
  • 第2项(加入书签,本地持久化)
  • 第3项(加入书签,本地持久化)
  • 第4项(未加入书签,来自第三方API)

...等

我希望视图从控制器中获取所有item的列表,并且不知道item的来源,但应该只知道每个item已添加书签以便可以显示(例如,因此用户可以将未加书签的item标记为已添加书签)。

泛型将是用其他语言解决这个问题的一种方法,但唉,Ruby没有泛型(没有抱怨)。在Ruby / Rails中,包装/构造这些模型的最佳方法是什么,因此视图只需要担心一种item(实际上幕后有两种类型?)

1 个答案:

答案 0 :(得分:1)

我建议想出一个对象,负责从第三方API和你的数据库中获取项目,这样的操作的结果将是一个响应相同方法的项目数组,无论如何他们来自哪里。

这是一个关于我如何去做的例子:

class ItemsController < ApplicationController
  def index
    @items = ItemRepository.all
  end
end

在上面的代码中,ItemRepository负责从数据库和第三方API中获取项目,然后视图将遍历@items实例变量。

以下是ItemRepository的示例实现:

class ItemRepository
  def self.all
    new.all
  end

  # This method merges items from the API and
  # the database into a single array
  def all
    results_from_api + local_results
  end

  private

  def results_from_api
    api_items.map do |api_item|
      ResultItem.new(name: api_item['name'], bookmarked: false)
    end
  end

  # This method fetches the items from the API and
  # returns an array
  def api_items
    # [Insert logic to fetch items from API here] 
  end

  def local_results
    local_items.map do |local_item|
      ResultItem.new(name: local_item.name, bookmarked: true)
    end
  end

  # This method is in charge of fetching items from the 
  # database, it probably would use the Item model for this
  def local_items
    Item.all 
  end
end

拼图的最后一部分是ResultItem,请记住ItemRepository.all将返回一个包含此类对象的数组,所以您需要做的就是存储视图所需的信息这个课上的项目。

在此示例中,我假设所有视图需要了解每个项目的名称以及是否已添加书签,因此ResultItem会响应bookmarked?name方法:

class ResultItem
  attr_reader :name

  def initialize(name:, bookmarked:)
    @name = name
    @bookmarked = bookmarked
  end

  def bookmarked?
    !!@bookmarked
  end
end

我希望这有帮助:)

PS。很抱歉,如果某些课程名称过于通用,我无法想出更好的内容