5

在不触发任何数据库操作的情况下创建新的 Ruby/Rails 对象的最佳方法是什么?

例如,如果我有一个任务类

class Task < ActiveRecord::Base
  has_many :tags
  has_one :location

end

我想从看起来像这样的缓存数据创建一个

task_json = { 
  id: 1, 
  title: 'My Task', 
  tags: [ 
    { title: 'Tag1' }, 
    { title: 'Tag2'} 
  ]
  location: { lat: 46.0, lon: -120.1 } 
} 

我想重构对象,但不触发任何数据库交互。

@task = Task.new
@task.id = task_json['id']
@task.title = task_json['title']
@task.location = Location.new(:lat => task_json['location']['lat'], :lon => task_json['location']['lon'])

@task.tags = ...

理想情况下,一旦构建了对象,就不会以任何方式进行保存或数据库交互。

4

2 回答 2

8

您可以尝试以这种方式JSON.parse在您的 JSON 字符串上使用task_json

task = Task.new(JSON.parse(task_json))
于 2013-05-16T17:53:44.463 回答
2

在不触发任何数据库操作的情况下创建新的 Ruby/Rails 对象的最佳方法是什么?

例如,如果我有一个任务类

class Task < ActiveRecord::Base

普通的旧 Ruby 对象

如果你想要一个不持久的 PORO(普通的旧 Ruby 对象),为什么还要子类ActiveRecord::Base?您可以将其放在任何可自动加载的路径中,例如app/models/task.rb

class Task
  attr_reader :tags, :location, ...
  def initialize(...)
    @tags = ...
    @location = ...
    ...
  end
end

然后在其他地方创建它,例如:

task = Task.new(...)

然后您可以访问其部分,例如:

task.tags

您可以在其中传入解析的 JSON、JSON 字符串、args 等。

但是,散列本身JSON.parse(some_json_string)是一个 Ruby 对象,因此您可以轻松地使用它。它也不会触发任何数据库操作。:) 你可能使用像 Task 这样的类的主要原因是让它更清楚它是什么以及对它的期望,但是哈希也很容易使用。只是取决于。

如果你真的想要一个只读的 ActiveRecord 模型,你可以使用几个 gem 之一。我写了一个其他人贡献的名为activerecord-be_readonly,但是你需要这样的东西的时间应该很少,而且它更适合从数据库读取数据然后尝试不允许数据库通过该模型更新该特定表。

仅在从 JSON 创建时将 ActiveRecord 模型实例设为只读

在您的评论中,您说如果我理解正确,您只想将其从缓存中提取为只读。

看看activerecord-be_readonly gem 如何改变 AR 行为:https ://github.com/garysweaver/activerecord-be_readonly/blob/master/lib/activerecord-be_readonly/model.rb

我猜您在使用 JSON 哈希初始化模型时会想要设置一个标志,当设置该标志时,类似的方法可以查看和引发ActiveRecord::ReadOnlyRecord或类似的方法。

不过,这只会保护您使用这些方法的模型。如果您与其他模型有关联,除非它们使用类似的方法,否则它不会保护它们。最后,如果您绝对必须这样做,那么使用 PORO 和常规 AR 模型可能会更好。

但是,这听起来使用起来会很痛苦。我会避免任何让用户(或开发人员)挠头的事情。

于 2013-05-16T18:18:24.627 回答