从Json创建一个ActiveRecord实例

时间:2013-05-15 23:48:10

标签: ruby-on-rails caching activerecord

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

例如,如果我有一个Task类

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 = ...

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

2 个答案:

答案 0 :(得分:7)

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

task = Task.new(JSON.parse(task_json))

答案 1 :(得分:2)

  

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

     

例如,如果我有一个Task类

     

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模型,你可以使用其中的几个宝石中的一个。我写了一个其他几个人为activerecord-be_readonly做出贡献的一个,但是你需要这样的东西的时间应该很少,而且它更适合从数据库读取数据然后尝试不允许通过该模型对该特定表进行DB更新。

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

在你的评论中,如果我理解正确的话,你说你只想把它从缓存中拉出来。

看看activerecord-be_readonly宝石如何在这里改变AR行为:https://github.com/garysweaver/activerecord-be_readonly/blob/master/lib/activerecord-be_readonly/model.rb

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

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

然而,这听起来像是一个痛苦的使用。我会避免任何使用户(或开发人员)过多地抓挠他/她的头的事情。