Save an Active Records Array

save an active records array

a.each(&:save)

This will call B#save on each item in the array.

Save an array of ActiveRecords objects

Well, you should call save method on each of them:

@reservations.each(&:save)

Or install some third party gem that provides a multiple insert feature. You should also rewrite your if statement, since the expression above will always return the collection itself, thus evaluating to true.

Ruby convert array of active records or objects into array of hashes

The create method actually persists each hash individually, as shown in the source code, so probably it's not what you are looking for. Either way the following code would do the job:

  Account.create!(persons.map { |person| Hash[:person_id, person.id] })

If you need to create all records in the same database operation and are using rails 6+ you could use the insert_all method.

  Account.insert_all(persons.map { |person| Hash[:person_id, person.id] })

For previous versions of rails you should consider using activerecord-import gem.

  # Combination(1).to_a converts [1, 2, 3] to [[1], [2], [3]]
Account.import [:person_id], persons.pluck(:id).combination(1).to_a

Saving and retrieving an Array in Rails

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.

Storing arrays in database using ActiveRecord

If you use serialize then you shouldn't have to worry about how the data is stored within the text field, although it's actually YAML.

serialize is documented in the Rails/ActiveRecord API (scroll down to the section headed "Saving arrays, hashes, and other non-mappable objects in text columns")

For display, you need a format that is understandable to users and that can be easily converted back into an array in your code. Comma- or space-delimited?

Formatting for output:

delim = ',' # or ' ' for spaces, or whatever you choose
array.join(delim)

Converting back into an array might work as follows:

num_array = nums.split(delim).map(&:to_i) # or to_f if not integers

or perhaps using String#scan?

num_array = nums.scan(/\d+/).map(&:to_i) # for positive integers


Related Topics



Leave a reply



Submit