madeintandem / jsonb_accessor

Adds typed jsonb backed fields to your ActiveRecord models.
MIT License
1.1k stars 93 forks source link

Calling jsonb column doesn’t return default values #175

Open borisrorsvort opened 9 months ago

borisrorsvort commented 9 months ago

Given this configuration

  jsonb_accessor :voting_options, voting_options_type: [:string, { default: "single", store_key: :type }] 

With an empty db column i get an empty hash

irb(main):015:0> a.voting_options
=> {}
irb(main):016:0> a.voting_options_type
=> "single"
irb(main):017:0> a.voting_options["type"]
=> nil
irb(main):018:0>

I would be expecting to get the default values

{
    "type": "single"
}
haffla commented 9 months ago
jsonb_accessor :voting_options, voting_options_type: [:string, { default: "single", store_key: :type }]

means that the default for the accessor voting_options_type should be "single".

borisrorsvort commented 9 months ago

@haffla exactly.

Though we noticed that the bug does not occur when creating a new object. In our case:

a  = Post::IdeasRequest.new
a.voting_options  #> {"type"=>"single"}

This only happens if the column default value is {}, nil or when only one value has been set manually after.

example:

Given this other config

jsonb_accessor :voting_options,
                 voting_options_type:        [:string, { default: "single", store_key: :type }],
                 voting_options_budget_rule:   [:boolean, { default: false, store_key: :budget_rule }]

When assigning only one manually:

irb(main):039:0> a = Post::IdeasRequest.new
=>
#<Post::IdeasRequest:0x000000010e06bf58
...
irb(main):040:0> a.voting_options
=> {"type"=>"double", "budget_rule"=>false}
irb(main):041:0> a.voting_options = {}
=> {}
irb(main):042:0> a.voting_options_type = "single"
=> "single"
irb(main):043:0> a.voting_options
=> {"type"=>"single"}
irb(main):044:0>

While i’m expecting to always have at least all the defined keys in the returned values when calling voting_options.

haffla commented 9 months ago

I think this gem wasn't developed with using the jsonb field directly in mind. In your case voting_options. But rather like

idea_request.voting_options_type = "something"
idea_request.voting_options_budget_rule = "another thing"
idea_request.save!

Basically you can store anything in voting_options and use "accessors" to access fields in the hash.

I also have to say that I understand your report, though I am almost 100% sure that there was someone in the past who opened an issue because the default values are saved to the database. So I am not sure if this here is a bug report or feature request. It could be something configurable. Some people prefer it this way and other that way.

haffla commented 9 months ago

On another note. I would be in favour for your suggested behaviour and would accept a PR. I don't have capacity to work on it myself.