I have a Damage
table that has the following fields:
I'd like to add another field to store Damagepoints
, which are JSON objects that look like this:
{ top: 50, left: 100 }
Top and left are the coordinates of the damagepoint
on a diagram. The damagepoints
are added/removed by the user using Javascript.
However, I'd like to store, in one field, an array of these damagepoints
, like this:
@damage.damagepoints = [{left: 40, top: 99}, {left: 100, top: 35}, {left: 150, top: 95}]
I don't want to do this using a Damagepoint
table with a has_many
relationship because all of the changes to this will be done using Javascript, and if Damagepoints
are created or removed by the user, I just want to pass from the client the updated array of damagepoints
and replace the old one in the database with the new array. If I used a has_many
relationship, I'd have to delete all of the Damagepoints
and create each one new every time the array was updated (because it is too complicated and there is no benefit from deleting/adding specific damagepoints, as I don't need to track history).
What is the easiest way to store data like @damage.damagepoints
(above)? All I need to do with it is pass it (via the controller) to an html5 data-attribute so that it can be used by the Javascript to add the existing damagepoints
to the diagram (based on their coordinates) and then pass an updated array (from the html5 data-attribute) back to the controller via an AJAX call when the user clicks the 'Save' button.
I am using Rails 4.2 and Postresql.
Thanks!
As you're using postgres, you're in luck: postgres has a native json type. This is way better than using serialize to store the data as some form of encoded string, because postgres has a rich family of operators that allow you to query against that json data.
If you are using postgres 9.4 then you can also use the jsonb type. This is generally better as it stores a processed version of the data (i.e. it doesn't have to keep reparsing the data over and over again) and it allows indexes.
Rails supports this out of the box (see here), you just need to add a column of type json(b). If your migration contains
create_table :damages do |t|
t.string :description
t.jsonb :damage_points
end
then
Damage.create(damage_points: [{left: 40, top: 99}, {left: 100, top: 35}])
would create a row with the damage points data store as json. The only thing to watch out for is that although your input data has symbols as the keys in the hashes, when fetching from the database you'll always get strings back as keys.
Serialize your data before writing to the database and deserialize when reading. You can override the getter and setter in the model.
Two good options for serialization would be JSON
and YAML
.
Rails comes with the json
gem so you can just call to_json
on any object or array. Then you need to read it, JSON.parse(some_json)
.
Similarly, Rails comes with yaml
so you can use YAML.dump(text)
and YAML.load(text)
. YAML is a little more human-readable than JSON in my opinion, but if you're passing the data to Javascript, JSON is the standard.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With