问题
I'm developing an e-learning in Rails and I want to save a set of Arrays to the database, with the aim of tracking a user's progress through the various sections of the e-learning.
I've come across this question and answer:
Storing arrays in database : JSON vs. serialized array
...which sounds like it might be useful, but I can't figure out how to integrate it into the Rails project I'm developing.
Given that I'm pretty much a Rails noob, could someone explain to me, in plain English (or alternatively plain code) how I would:
a) save to a database an Array which holds a sequence of 'false' Booleans when a user initially signs up.
b) retrieve and update that Array from various pages throughout the e-learning.
I would set out what I have tried, but it's just been wild stabs in the dark and I don't really know where to start. Should the Comment class be saved in the controllers folder? Or is it, in my example, actually the User class (which, similarly, extends ActiveRecord)?
Once again, any help (ideally explaining where the code belongs) much appreciated.
UPDATE
I've been asked to be more specific, so I will try:
I have a user table in the database, which (predictably) has several fields, including email, username, etc. I'd like to add 5 more fields to the user table, each storing an Array to track the user's progress through each of the 5 sections. I'm envisaging, when a user opens a piece of content, the Array would be updated and the appropriate index would be updated to 'true' to flag that THAT part of the section is complete.
I hope that helps...
RE-UPDATE
When a user first signs up I want the Arrays to be set with a sequence of 'false' Booleans. From which file would I set the Arrays? Is that done in User? At the moment I'm trying this, but I don't think the values are being set - although it's not throwing an error.
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
I have also checked which routes are mapped where, via 'rake routes'; users/sign_up is mapped to devise/registrations/new. So does the serialize code, suggested below, go there?
回答1:
You mentioned the Comment and User class extend ActiveRecord. These are models and they go in the app/models folder.
Saving arrays to the database is very straightforward as explained in the answer you linked to. All you have to do to integrate it into your project is declare which attribute you want to store Arrays in and they will be automagically serialized upon saving or updating and deserialized when you want to read them back.
You should definitely post any code you have already. I'll assume the attribute you want to serialize is in the Comment model and it's called choices
(but of course it can be anything) and it is a text field (not a string field as this might be too short if your arrays grow more than 255 characters when serialized):
# app/models/comment.rb
class Comment < ActiveRecord::Base
serialize :choices
end
That's it! Now when ever you assign a value to that attribute @comment.choices = [false, false]
it will be automatically serialized as YAML when you save and then it'll be deserialized when you read it:
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
To explain what's going on "under the hood" when you save the record with an array value assigned to the choices
field ActiveRecord knows that you want to serialize it since you declared serialize :choices
in your Comment class. It will take that array value and serialize it like this:
YAML.dump(choices)
this will convert the array into this string:
"---\n- false\n- false\n- true\n- stuff\n- whatever\n"
That is the YAML representation (serialization) of the array. To read it back in (when you call comment.choices
) ActiveRecord will take the serialized string and deserialize it:
YAML.load(choices)
That will then convert the YAML string back into a Ruby array.
To summarize:
- Add a text field to your model e.g.
choices:text
when you create the migration. - Declare
serialize :choices
in your model. - Use as normal.
Hope that helps.
来源:https://stackoverflow.com/questions/25916449/saving-and-retrieving-an-array-in-rails