如何在不使用数据库的情况下在 Rails 应用程序中存储 Ruby 对象?

问题描述

给定

  • 这个 Ruby 类:

    class Quiz
      attr_accessor :topic,:course,:highest_grade,:failing_grade,:answers_by_questions
    
      def initialize(topic,course,highest_grade,failing_grade)
        @topic = topic
        @course = course
        @highest_grade = highest_grade
        @failing_grade = failing_grade
        @answers_by_questions = Hash.new()
      end
    
      def add_question(question,answer)
        @answers_by_questions[question] = answer
      end
    end
    
  • 这个测验类的实例:

    ch1_history_quiz = Quiz.new("Chapter 1","History",100,65)
    ch1_history_quiz.add_question("Which ancient civilisation created the boomerang?","Aboriginal Australians")
    

目标

保存此测验对象以供该应用的所有用户稍后访问。


问题

如何在 Rails 6.0 中存储和访问这个测验对象而不在数据库中表示它?


可能的解决方

  • 是否可以使用 Marshal 对对象进行 pickle 并保存以备后用?

到目前为止我检查过的内容

SO - Store json object in ruby on rails app:因为这是 JSON,所以在 JSON 格式和解析格式之间来回切换更直观。

SO - Can I create a database of ruby classes?:我真的没有得到这个问题的答案。部分链接已损坏。不过,我认为这个问题非常相似。

解决方法

是否可以使用Marshal来pickle对象并保存为 以后用吗?

是的,使用相同的代码作为示例,您可以序列化和反序列化对象,恢复原样。

irb(main):021:0> marshalled = Marshal.dump(ch1_history_quiz)
=> "\x04\bo:\tQuiz\n:\v@topicI\"\x0EChapter 1\x06:\x06ET:\f@courseI\"\fHistory\x06;\aT:\x13@highest_gradeii:\x13@failing_gradeiF:\x1A@answers_by_questions{\x06I\"6Which ancient civilisation created the boomerang?\x06;\aTI\"\eAboriginal Australians\x06;\aT"
irb(main):022:0> deserialized = Marshal.load(marshalled)
=> #<Quiz:0x00007f81d3995348 @topic="Chapter 1",@course="History",@highest_grade=100,@failing_grade=65,@answers_by_questions={"Which ancient civilisation created the boomerang?"=>"Aboriginal Australians"}>

另一种更易读的选项是以 YAML 格式序列化您的对象:

irb(main):030:0> yamled = YAML.dump(ch1_history_quiz)
=> "--- !ruby/object:Quiz\ntopic: Chapter 1\ncourse: History\nhighest_grade: 100\nfailing_grade: 65\nanswers_by_questions:\n  Which ancient civilisation created the boomerang?: Aboriginal Australians\n"
irb(main):031:0> deserialized = YAML.load(yamled)
=> #<Quiz:0x00007f81d398cb80 @topic="Chapter 1",@answers_by_questions={"Which ancient civilisation created the boomerang?"=>"Aboriginal Australians"}>

使用这两个选项中的任何一个,您都可以稍后将其保存在数据库文本字段中(有足够的空间来保存大对象)、纯文本文件或您选择的任何内容。
此外,需要牢记的重要事项是 the security issues 关于使用 marshal 或 yaml,因此必须始终从受信任的来源加载对象。