Skip to content

Conversation

@razumau
Copy link
Contributor

@razumau razumau commented Nov 7, 2025

Usage

ticket.custom_field["field name"]            # get
ticket.custom_field["field name"] = "value"  # set; you also need to call ticket.save!

How it works

When #custom_field is called for the first time on any ticket for the client instance, we fetch all ticket_fields and store a mapping from field names to their IDs on that client instance. Following #custom_field will reuse this mapping.

You can call client.refresh_custom_fields_metadata if you expect that definition of fields have changed since the data was loaded.

To enable bracket syntax, custom_field returns a CustomFieldAccessor object with [](field_name) and []=(field_name, value) methods.

The mapping is stored inside account_data hash on a client: I’ve decided to give a more generic name to give future additions an obvious placement. However, we expose a custom fields-specific refresh_custom_fields_metadata method on a Resource so that resources can refresh only that part of account_data which is relevant for them.

Should we preload this metadata?

Initially I added a config key that would enable this preloading and fetch ticket fields during client initialization. We can potentially go back to this, but I think that memory usage is low enough not to warrant an additional configuration flag.

Note on memory usage

A custom fields mapping stored on a client looks like this:

{
  "Subject" => 9000000000001,
  "Description" => 9000000000002,
  "Field one" => 9000000000003,
  "Field two" => 9000000000004
}

(It includes all fields, not only custom ones).

If you have 1000 custom fields with 30-character names, this mapping will need about 40 KB. This shouldn’t matter for most cases, but if you simultaneously have in memory thousands of clients for accounts with thousands of custom fields, memory usage of these mappings might become noticeable.

Alternative implementation: no accessor, worse method names

I’ll squash these commits before merging but for now I wanted to have a commit with a simpler approach (but arguably worse API).

ticket.custom_field_by_name("field name")
ticket.set_custom_field_by_name("field name", "value)

This doesn’t require an additional accessor class. I think ticket.custom_field["field name"] way is much better and worth a bit of complexity.

@razumau razumau force-pushed the jury.razumau/custom_fields branch from d71f21b to 048ef78 Compare November 7, 2025 16:05
@cryptomail
Copy link
Contributor

@razumau razumau force-pushed the jury.razumau/custom_fields branch from bfeeb82 to d471f70 Compare November 18, 2025 15:15
@razumau razumau force-pushed the jury.razumau/custom_fields branch 3 times, most recently from 4eb2647 to 85cd4bc Compare November 20, 2025 13:23
@razumau razumau changed the title add option to preload custom fields metadata add way to refer to custom fields by their names Nov 20, 2025
@razumau razumau force-pushed the jury.razumau/custom_fields branch from 85cd4bc to 68805ae Compare November 20, 2025 14:12
@razumau
Copy link
Contributor Author

razumau commented Nov 20, 2025

@razumau razumau marked this pull request as ready for review November 20, 2025 14:20
@razumau razumau requested a review from a team as a code owner November 20, 2025 14:20
Comment on lines +564 to +573
def find_by_name(field_name)
@ticket.refresh_custom_fields_metadata unless @ticket.account_data.has_key?(:custom_fields)

custom_field_id = @ticket.account_data[:custom_fields][field_name]
custom_field = @ticket.custom_fields.find { |cf| cf["id"] == custom_field_id }
raise ArgumentError if custom_field.nil?

custom_field
end
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could check if custom_field_id is nil before doing find to save us some work if we're never going to find anything. We can add a message to ArgumentError to help with debugging.


it "stores custom fields metadata on a client" do
_custom_field_value = @ticket.custom_field["Custom field name"]
expect(@ticket.account_data[:custom_fields]["Custom field name"]).to eq(9961714922394)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does 9961714922394 work? 😅

Copy link
Member

@Thomascountz Thomascountz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just some questions. I'd love to benchmark things once we understand how folks are using client objects.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants