【问题标题】:Saving and retrieving an Array in Rails在 Rails 中保存和检索数组
【发布时间】:2014-09-18 15:13:25
【问题描述】:

我正在使用 Rails 开发电子学习,我想将一组数组保存到数据库中,目的是跟踪用户在电子学习各个部分的进度。

我遇到过这个问题和答案:
Storing arrays in database : JSON vs. serialized array
...听起来它可能很有用,但我不知道如何将它集成到我正在开发的 Rails 项目中。

鉴于我几乎是 Rails 菜鸟,有人可以用简单的英语(或者简单的代码)向我解释我会如何:
a) 将一个数组保存到数据库中,该数组在用户最初注册时保存一系列“假”布尔值。
b) 在整个电子学习过程中从各个页面检索和更新该数组。

我会列出我尝试过的东西,但这只是在黑暗中的狂野刺伤,我真的不知道从哪里开始。注释类应该保存在控制器文件夹中吗?或者,在我的示例中,它实际上是 User 类(类似地,它扩展了 ActiveRecord)?

再次感谢任何帮助(最好是解释代码所属的位置)。

更新

我被要求更具体,所以我会尝试:
我在数据库中有一个用户表,其中(可以预见)有几个字段,包括电子邮件、用户名等。我想在用户表中再添加 5 个字段,每个字段都存储一个数组来跟踪用户在每个字段中的进度5个部分。我设想,当用户打开一段内容时,数组将被更新,并且相应的索引将被更新为“真”以标记该部分的该部分已完成。

希望对你有帮助……

重新更新

当用户第一次注册时,我希望用一系列“假”布尔值设置数组。我将从哪个文件设置数组?这是在用户中完成的吗?目前我正在尝试这个,但我认为没有设置值 - 尽管它没有引发错误。

class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  serialize :leadership_styles_progress
  serialize :skills_progress
  serialize :safeguarding_progress
  serialize :tools_progress

  before_create :set_progress_vars

  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable
  validates :age, presence: { :message => ": Please choose your age" }
  validates :section, presence: { :message => ": Please choose the section you belong to"}
  has_many :posts

  private

  def set_progress_vars
    self.leadership_styles_progress = [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false]
    self.skills_progress = [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false]
    self.safeguarding_progress = [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false]
    self.tools_progress = [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false]
  end

end

我还通过“rake routes”检查了哪些路线被映射到哪里; users/sign_up 映射到 devise/registrations/new。那么下面建议的序列化代码会去那里吗?

【问题讨论】:

  • 你能试着解释清楚一点吗?用户的课程有很多页面,您想存储他们访问过的页面吗?理想情况下,只有相关表的某种形式的简单数据库结构会很有用
  • 您(或将来)是否需要查询此数组?如果是这样,那么serialize 就是你的敌人,你最好在列表中使用单独的列或单独的表格。
  • 当用户登录(而不是注册)时,我需要反序列化数组并将其加载到局部变量中(我假设)。当他们查看新内容时,我将要更新数据库上的数组。 '序列化'可以吗?

标签: ruby-on-rails ruby arrays serialization deserialization


【解决方案1】:

您提到了 Comment 和 User 类扩展 ActiveRecord。这些是模型,它们位于 app/models 文件夹中。

如您链接到的答案中所述,将数组保存到数据库非常简单。将它集成到项目中所需要做的就是声明要将数组存储在哪个属性中,它们将在保存或更新时自动序列化,并在您想读回它们时反序列化。

您绝对应该发布您已经拥有的任何代码。我假设您要序列化的属性在 Comment 模型中,它被称为 choices (当然它可以是任何东西)并且它是一个文本字段(不是字符串字段,因为如果您的数组可能太短序列化时增长超过 255 个字符):

# app/models/comment.rb
class Comment < ActiveRecord::Base
  serialize :choices
end

就是这样!现在,当您为该属性 @comment.choices = [false, false] 分配一个值时,它会在您保存时自动序列化为 YAML,然后在您阅读时将其反序列化:

class CommentController < ApplicationController
  def create
    @comment = Comment.new choices: [false, false, true, 'stuff', 'whatever']
  end

  def show
    @comment = Comment.find params[:id]
    @comment.choices # returns [false, false, true, 'stuff', 'whatever']
  end
end

为了解释当您使用分配给choices 字段的数组值保存记录时“幕后”发生了什么,ActiveRecord 知道您想要序列化它,因为您在 Comment 类中声明了 serialize :choices。它将获取该数组值并像这样序列化它:

YAML.dump(choices)

这会将数组转换成这个字符串:

"---\n- false\n- false\n- true\n- stuff\n- whatever\n"

即数组的YAML 表示(序列化)。要读回它(当您调用 comment.choices 时),ActiveRecord 将获取序列化字符串并对其进行反序列化:

YAML.load(choices)

这会将 YAML 字符串转换回 Ruby 数组。

总结一下:

  • 为您的模型添加一个文本字段,例如choices:text 创建迁移时。
  • 在您的模型中声明 serialize :choices
  • 正常使用。

希望对您有所帮助。

【讨论】:

  • 所以如果我有一个用户表 - 和一个用户模型 - 'serialize :choices' 应该进入用户模型吗?我很欣赏答案,但我仍然不知道将代码放在哪里。如果没有对用户的引用,如何确保将数组保存到正确的用户 (current_user)?
  • 我也不太明白为什么 :choices 被定义为一个符号,然后被称为一个方法。另外为什么它最初是在一个冒号之前,然后是一个冒号?对此有合理的解释,还是只是 Ruby 的怪癖之一?对不起。我可能有点沮丧。
  • 我无法真正回答你们中的一些问题,因为它们由您决定。 choices 在用户模型中?我不知道,您是这样定义架构的吗?你想把这些数据保存在哪里?由你决定。例如,假设您确实在 User 表中添加了一个名为 choices 的字段,您声明要在 User 模型中使用 serialize :choices 序列化该字段。您使用符号引用该字段,因为它是字段的名称,但它也是 User 模型上的一个属性(因为它是 User 表中的一个字段)
  • ...因此它将可以通过用户实例上的同名方法获取和设置:user = User.new; user.choices = ['stuff']; user.choices # returns ['stuff']。在冒号后面的部分:Comment.new choices: [] 这只是 Ruby 的新哈希表示法,它等价于:Comment.new :choices =&gt; []。因此,它只是传递给模型的属性哈希值,以将它们大量分配给您newing 的实例。
  • 我想在用户表中为每个用户保存 4 个数组,所以每个用户都有 4 个数组。如我上面的代码所示,我在用户中添加了序列化:leadership_styles_progress...等等,但它们似乎无法通过该方法名称访问,即:current_user.leadership_stlyes_progress。知道为什么吗?另外我会从哪里发送这些初始值?如,哪一点代码?谢谢。
猜你喜欢
  • 2016-10-24
  • 1970-01-01
  • 1970-01-01
  • 2018-05-15
  • 1970-01-01
  • 2021-07-12
  • 2020-07-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多