使用Grape创建一个只使用Ruby对象而不是数据库或Rails的API

时间:2015-08-02 05:09:18

标签: ruby rack grape-api

我正在尝试使用Grape仅使用Ruby对象创建API。我不想使用数据库/ Rails / ActiveSupport / etc - 只是Rack,Ruby和Grape。

我已为Directory定义了一个我想通过API进行交互的类。因此,Directory#sort_by("last_name")会返回JSON数据,其中包含PeopleDirectory个对象的列表。我还有一个方法Directory#create_person(attributes),它接受​​一个字符串并使用它将Person个对象添加到Directory。该目录在创建时填充了人员。

我是使用Rack和Grape的新手,所以我不确定在哪里/如何创建我的Directory对象,并通过我的Grape API类中的GET / POST来访问它。在这个类中使用一个类变量似乎有效,即:

module API
  class DirectoryAPI < Grape::API
    format 'json'

    @@directory = Directory.new("1.txt", "2.txt", "3.txt")

    get 'last_name' do
      @@directory.sort_by("last_name")
    end
  end
end

但使用类变量似乎错了。是否有更好/更清晰的方法来创建我的Directory对象?也许在我的config.ru文件中?或者我可以通过Directory内部的类方法来实现吗?

2 个答案:

答案 0 :(得分:1)

您要找的是singleton

  

通常,单身人士用于集中管理内部或外部资源,并为他们提供全球访问权限。

不幸的是,Ruby对单身人士的表现并不好。但是你可以使用仅由类方法组成的&#34;类,#34;这个article中倡导的第二个战略。

我相信您正在处理我几个月前完成的编码挑战。在我的回答中,我使用了一个仅由类方法组成的&#34;类#34;叫API::Store。这是rspec -fd的输出:

API::Store
  ::add
    adds record to store
    appends data line to file
  ::has_line?
    instantiates a record from the data line
    without the record in the store
      should equal false
    with the record in the store
      should equal true
  ::new
    should raise NoMethodError
  ::records
    with original file
      on initial access
        should eq Records
      on subsequent access
        should eq Records
    when file replaced
      should eq OtherRecords

Finished in 0.07199 seconds (files took 2.68 seconds to load)
9 examples, 0 failures

请注意,Store无法实例化;如果你尝试,它会抛出一个NoMethodError。但这不是问题。在Grape端点中,您可以调用Store.records来访问数据。

至于记录的排序,这应该在另一个类中完成。为什么StoreDirectory要对其文件中的数据进行排序?

最后,您询问了初始准备的位置(当然不是初始化)。您可以在config.ru中准备单件,以便在应用程序启动时准备就绪:

# config.ru

# load application code here

file = File.open('data/records.txt', 'a+')
at_exit { file.close }

API::Store.file = file
run API::Base

挑战instructions说&#34;您可以使用完成它所需的任何资源,&#34;所以大概是允许在Stack Overflow上询问。如果您正在为求职申请进行此项挑战,请在提出问题时提及,因为对于那些接听通知的人来说,这只是公平的。在你的采访中也提到你在SO上得到了帮助是明智的。祝你好运,编码愉快。

答案 1 :(得分:0)

我在您的示例中看到的主要问题不是完全使用类变量,而是在API控制器代码中实例化内联数据。理想情况下,数据应该更加自包含,因此您可以从代码中的其他位置访问完全相同的数据。如果您创建类似于轻量级数据访问模块的API,那么您将在路由控制器中使用熟悉的模式 - 如果需要,也可以轻松迁移到使用SQL或其他数据存储。

有许多有效的方法,但我可能会创建一个新的单例对象来表示您的数据源,并将其连接到您的硬编码数据,就像它是表格一样。这里的最终结果有点像使用Sequel(但你可以按照你喜欢的任何其他模式):

<强> inline_data.rb

module InlineDB
  TABLES = Hash[
     :directory => Directory.new("1.txt", "2.txt", "3.txt")
  ]

  def self.[] table_name
    TABLES[table_name]
  end
end

<强> app.rb

require_relative 'inline_data' # actual path may be more structured
module API
  class DirectoryAPI < Grape::API
    format 'json'

    get 'last_name' do
      InlineDB[:directory].sort_by("last_name")
    end
  end
end