Skip to content

Commit

Permalink
Support JSON serialization in Hanami::DB::Struct
Browse files Browse the repository at this point in the history
We would like structs in Hanami to support simple JSON serialization
following the `#to_json` convention.

There have been discussions of this functionality in both ROM and
Dry-Struct projects, where this was rejected as not appropriate for
those gems:

- dry-rb/dry-struct#166
- rom-rb/rom#403

This adds a simple `#to_json` method to `Hanami::DB::Struct` to support
the simple case for serialization.
  • Loading branch information
krzykamil authored and alassek committed Oct 18, 2024
1 parent 5317bcc commit ec2942f
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 0 deletions.
8 changes: 8 additions & 0 deletions lib/hanami/db/struct.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ module DB
# @api public
# @since 2.2.0
class Struct < ROM::Struct
# @api public
# @since 2.2.0
#
# Simple conversion of attributes to JSON format, without this method, the instance of the struct gets converted
# to a string
def to_json(*args)
to_h.to_json(*args)
end
end
end
end
48 changes: 48 additions & 0 deletions spec/unit/struct_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# frozen_string_literal: true

RSpec.describe Hanami::DB::Struct do
let!(:config) do
ROM::Configuration.new(:sql, "sqlite::memory") do |conf|
conf.default.create_table(:users) do
primary_key :id
column :first_name, String
column :last_name, String
end

conf.relation(:users) do
schema(infer: true)
end
end
end

let(:rom) { ROM.container(config) }

before do
module Test
module Entities
class User < Hanami::DB::Struct
def full_name
"#{first_name} #{last_name}"
end
end
end

class UserRepo < ROM::Repository[:users]
struct_namespace Entities
end
end
end

describe "#to_json" do
before do
rom.relations[:users].changeset(:create, id: 1, first_name: "L", last_name: "L").commit
end

it "converts to json" do
repo = Test::UserRepo.new(rom)
struct = repo.users.by_pk(1).one!
expect(struct.full_name).to eq "L L"
expect(struct.to_json).to eq "{\"id\":1,\"first_name\":\"L\",\"last_name\":\"L\"}"
end
end
end

0 comments on commit ec2942f

Please sign in to comment.