Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Prefix / Suffix feature #182

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
mmarusyk wants to merge 2 commits into madeintandem:master
base: master
Choose a base branch
Loading
from mmarusyk:feature/prefix-suffix-options

Conversation

Copy link

@mmarusyk mmarusyk commented May 6, 2025
edited by ashkulz
Loading

This PR introduces an improvement for utilizing prefix and suffix options for attribute names in jsonb_accessor.

Why?

In some cases, it suffices to store certain information about orders in jsonb format when it's only needed for historical purposes or for generating invoices, etc.

Results

How it currently looks in the Order model:

class Order < ApplicationRecord
 jsonb_accessor :contact_details,
 contact_details_email: [:string, { store_key: :email }],
 contact_details_last_name: [:string, { store_key: :last_name }],
 contact_details_first_name: [:string, { store_key: :first_name }],
 contact_details_phone_number: [:string, { store_key: :phone_number }]
 jsonb_accessor :billing_details,
 billing_details_email: [:string, { store_key: :email }],
 billing_details_last_name: [:string, { store_key: :last_name }],
 billing_details_first_name: [:string, { store_key: :first_name }],
 billing_details_phone_number: [:string, { store_key: :phone_number }],
 billing_details_full_address_line: [:string, { store_key: :full_address_line }]
 jsonb_accessor :shipping_details,
 shipping_details_full_address_line: [:string, { store_key: :full_address_line }]
end

How it will look after implementing prefixes:

class Order < ApplicationRecord
 jsonb_accessor :contact_details,
 email: [:string, { prefix: true }],
 last_name: [:string, { prefix: true }],
 first_name: [:string, { prefix: true }],
 phone_number: [:string, { prefix: true }]
 jsonb_accessor :billing_details,
 email: [:string, { prefix: true }],
 last_name: [:string, { prefix: true }],
 first_name: [:string, { prefix: true }],
 phone_number: [:string, { prefix: true }],
 full_address_line: [:string, { prefix: true }]
 jsonb_accessor :shipping_details,
 full_address_line: [:string, { prefix: true }]
end

In rails console:

order.billing_details #=> {"email"=>"scottie_harris@kihn-rowe.test", "last_name"=>"Mosciski", "first_name"=>"Chi", "phone_number"=>"475912955432", "full_address_line"=>"Suite 897 932 Nitzsche Shoal, Tammiborough, MI 90349-4217"}
order.billing_details_first_name #=> "Chi"
order.contact_details_first_name #=> "Marquita"
order.contact_details #=> {"email"=>"ralph@casper.test", "last_name"=>"Wunsch", "first_name"=>"Marquita", "phone_number"=>"278587369859"}
order.update(contact_details_first_name: "Mike", billing_details_first_name: "John") #=> true
order.reload.billing_details #=> {"email"=>"scottie_harris@kihn-rowe.test", "last_name"=>"Mosciski", "first_name"=>"John", "phone_number"=>"475912955432", "full_address_line"=>"Suite 897 932 Nitzsche Shoal, Tammiborough, MI 90349-4217"}
order.reload.contact_details #=> {"email"=>"ralph@casper.test", "last_name"=>"Wunsch", "first_name"=>"Mike", "phone_number"=>"278587369859"}
order.contact_details_last_name="Marsk" #=> "Marsk"
order.contact_details_last_name #=> "Marsk"
order.contact_details #=> {"email"=>"ralph@casper.test", "last_name"=>"Marsk", "first_name"=>"Mike", "phone_number"=>"278587369859"}
irb(main):012:0> order.save #=> true
irb(main):013:0> Order.contact_details_where(last_name: "Marsk") #=>
[#<Order:0x00007f7a0a85fc88
 id: 2,
 contact_details: {"email"=>"ralph@casper.test", "last_name"=>"Marsk", "first_name"=>"Mike", "phone_number"=>"278587369859"},
 billing_details: {"email"=>"scottie_harris@kihn-rowe.test", "last_name"=>"Mosciski", "first_name"=>"John", "phone_number"=>"475912955432", "full_address_line"=>"Suite 897 932 Nitzsche Shoal, Tammiborough, MI 90349-4217"},
 shipping_details: {"full_address_line"=>"38266 Durgan Motorway, Kulasmouth, NC 46602-3316"},
 contact_details_email: "ralph@casper.test",
 contact_details_last_name: "Marsk",
 contact_details_first_name: "Mike",
 contact_details_phone_number: "278587369859",
 billing_details_email: "scottie_harris@kihn-rowe.test",
 billing_details_last_name: "Mosciski",
 billing_details_first_name: "John",
 billing_details_phone_number: "475912955432",
 billing_details_full_address_line: "Suite 897 932 Nitzsche Shoal, Tammiborough, MI 90349-4217",
 shipping_details_full_address_line: "38266 Durgan Motorway, Kulasmouth, NC 46602-3316">]
irb(main):014:0> Order.contact_details_where(last_name: "Random") #=> []

Also, it works fine with store key:

class Order < ApplicationRecord
 jsonb_accessor :contact_details,
 email: [:string, { prefix: true, store_key: :e }], # Added store key
 last_name: [:string, { prefix: true }],
 first_name: [:string, { prefix: true }],
 phone_number: [:string, { prefix: true }]
 jsonb_accessor :billing_details,
 email: [:string, { prefix: true }],
 last_name: [:string, { prefix: true }],
 first_name: [:string, { prefix: true }],
 phone_number: [:string, { prefix: true }],
 full_address_line: [:string, { prefix: true }]
 jsonb_accessor :shipping_details,
 full_address_line: [:string, { prefix: true }]
end
order.contact_details #=> {"e"=>"frances.farrell@bernier.example", "last_name"=>"Kshlerin", "first_name"=>"Jessie", "phone_number"=>"567805903539"}
irb(main):021:0> order.contact_details_email="new_email@example.com" #=> "new_email@example.com"
order.contact_details_email #=> "new_email@example.com"
order.contact_details #=> {"e"=>"new_email@example.com", "last_name"=>"Kshlerin", "first_name"=>"Jessie", "phone_number"=>"567805903539"}
order.save #=> true
order.reload.contact_details #=> {"e"=>"new_email@example.com", "last_name"=>"Kshlerin", "first_name"=>"Jessie", "phone_number"=>"567805903539"}

For quering you can use name attribute without prefix/suffix:

Order.find(7).contact_details => {"e"=>"example@example.com"}
Order.contact_details_where(email: "example@example.com") # =>
[#<Order:0x00007f96bdd7a158
 id: 7,
 contact_details: {"e"=>"example@example.com"},
 billing_details: nil,
 shipping_details: nil,
 created_at: Sun, 07 Apr 2024 11:15:37.782726000 UTC +00:00,
 updated_at: Sun, 07 Apr 2024 11:15:37.782726000 UTC +00:00,
 contact_details_email: "example@example.com",
 contact_details_last_name: nil,
 contact_details_first_name: nil,
 contact_details_phone_number: nil,
 billing_details_email: nil,
 billing_details_last_name: nil,
 billing_details_first_name: nil,
 billing_details_phone_number: nil,
 billing_details_full_address_line: nil,
 shipping_details_full_address_line: nil>]

I'll be happy if we have this improvement in this gem. Thank you!

fixes #173

Previous conversation is in this pull request: #177

Copy link
Collaborator

ashkulz commented May 7, 2025

I'm not sure why CI is broken, don't think it's related to your change. I'll try to clean up the CI tomorrow 🤞

mmarusyk reacted with thumbs up emoji

Copy link
Collaborator

ashkulz commented May 8, 2025

I still need to get some additional permissions from @darcygarrett so I can't merge #183 right now, hopefully I should get them soon 🤞

Copy link
Collaborator

ashkulz commented May 13, 2025

@mmarusyk I like the idea, but having to specify prefix: true for every field doesn't strike me as good. I'd rather have something like

class Order < ApplicationRecord
 jsonb_accessor :contact_details, prefix: true,
 email: :string,
 last_name: :string,
 first_name: :string,
 phone_number: :string
 jsonb_accessor :billing_details, prefix: true,
 email: :string,
 last_name: :string,
 first_name: :string,
 phone_number: :string,
 full_address_line: :string
 jsonb_accessor :shipping_details,
 full_address_line: :string
end

Since the signature for the macro is def jsonb_accessor(jsonb_attribute, field_types) I think we can add keyword arguments there (especially since we're targeting Ruby 3.2+), but I'm not sure how well it'll play with the implicit Hash being passed for the field_types. Or do you have any other suggestion how we'd be able to DRY it up further?

Copy link
Author

@ashkulz Thanks for the feedback.

I agree that repeating prefix: true for every accessor isn't ideal. When I have time, I'll investigate ways to improve the macro, possibly by supporting keyword arguments.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

No reviews

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Prefix / Suffix feature request

2 participants

AltStyle によって変換されたページ (->オリジナル) /