我想学习在DATA字段中存储非结构化数据的智能方法
所以例如,如果我有表AuditLog,其字段为id | model_name |数据
在Data中,我希望存储基于model_name更改的各种类型的数据。我也想在数据中使用,因此出于性能原因,我可以使用JOIN输出这些记录。
实例 1 |照片| {photoid:1,photoname:“blah”} 1 |评论| {comment:1,commentcontent:“blah”,parent_type:“photo”,parent_id:“1”}
关于如何输入和输出的建议?
感谢
答案 0 :(得分:4)
我不确定我是否理解你的问题。但无论如何我会尽力回答。
如果您需要将模型转换为JSON,那么它非常简单。只需在模型上调用.to_json即可。然后你可以将它存储在TEXT列中。
要阅读它,您有两个选择:
将值读取为Ruby哈希值:ActiveSupport :: JSON.decode(some_json_text)
将值读取为对象 - 原始模型:获取上面的哈希值并将其作为参数传递给SomeModel.new。但是在这种情况下你必须要小心 - 相关的集合不起作用,不会设置id等。
如何自定义行为有很多选项,而且不清楚什么是最适合您的。我建议您阅读此帮助页面:http://railsapi.com/doc/rails-v3.0.0/classes/ActiveModel/Serializers/JSON.html并根据需要自定义您的解决方案。
在下面的示例中,我没有在模型上使用.to_json方法,因为示例中的方法更加可自定义。例如,您可以控制关联的行为(如果它们将被存储到日志中),等等。阅读链接的文档,您将看到。
以下是示例实现(内部读取注释)
class AuditLog < ActiveRecord::Base
#
# Stores shallow snapshot (without nesting into associations) of current
# model into the log in the JSON form
#
def self.audit(m)
# encode passed model into the JSON text
json = ActiveSupport::JSON.encode(m)
# create new log record and store it to the database
create(:model => m.class,
:data => json)
end
#
# Returns the logged item as a Ruby hash
#
# Your can access the result with ["attribute_name"]
#
def get_as_hash
# get the hash
result = ActiveSupport::JSON.decode(self.data)
# normally the json is { model_name => { attributes ... } } and we want the
# inner hash - so let's take it
result.values.first
end
#
# Returns the logged item as an original model (like Post, Comment, etc.)
#
# Beware that associations are filled only if they are stored in audit method
# So in case of Post: post.comments will always return an empty array
#
def get_as_model
# get hash
hash = get_as_hash
# create instance of the class model and pass the hash to init
# attribute values
m = self.model.constantize.new(hash)
# the initializator above ignore :id so let's set it manually
m.id = hash[:id]
# return the model
m
end
end
你可以这样使用它:
class Post < ActiveRecord::Base
has_many :comments
# after any successful change store the model to log
after_save :audit
private
# store the whole model to the log
def audit
AuditLog.audit(self)
end
end
希望你会喜欢它!
答案 1 :(得分:0)
这听起来像是一个NoSQL数据库(例如MongoDB)的一个很好的用例。有一个名为Mongoid(http://mongoid.org/)的Rails宝石,它更容易。
如果要保留ActiveRecord,可以始终将数据字段序列化为哈希。 http://api.rubyonrails.org/classes/ActiveRecord/Base.html#method-c-serialize
您可以这样做:
class AuditLog < ActiveRecord::Base
serialize :data, Hash
end
然后你就可以使用它:
@log = AuditLog.find(1)
@log.data = {:photo => {:photoid: 1, :photoname: "blah"}}
@log.data[:photo][:photoname] => "blah"
答案 2 :(得分:0)
这似乎是MongoDB的一项工作。我有一个类似的经历,我决定使用这个https://github.com/robertomiranda/mini_mongo
在Sinatra创建一个单独的服务