Skip to content

Query set enum input#341

Open
treagod wants to merge 3 commits intomainfrom
query-set-enum-input
Open

Query set enum input#341
treagod wants to merge 3 commits intomainfrom
query-set-enum-input

Conversation

@treagod
Copy link
Contributor

@treagod treagod commented Mar 6, 2026

This PR adds the possibility to use an enum value to set a field value

@treagod treagod force-pushed the query-set-enum-input branch from 5d64bf3 to ad5aa7d Compare March 6, 2026 21:14
@treagod treagod requested a review from ellmetha March 7, 2026 20:42
def initialize(
@id : ::String,
enum_values : Array(::String),
@enum_type : ::Enum.class | Nil = nil,
Copy link
Member

Choose a reason for hiding this comment

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

Why is this nilable? Technically, it shouldn't be possible to have an enum field without an actual enum class.

Comment on lines 16 to +17
enum_values : Array(::String),
@enum_type : ::Enum.class | Nil = nil,
Copy link
Member

Choose a reason for hiding this comment

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

I would argue that if we end up specifying the actual enum class to this method, then we could refactor the implementation of this field so that we only specify an @enum_class argument (instead of enum_type and enum_values, which do not appear useful given that values can be inferred from the type directly).

values.each do |key, value|
next unless value.is_a?(Field::Any | Model)
sanitized_values[key.to_s] = value
accepted, normalized_value = normalize_set_field_value(value)
Copy link
Member

Choose a reason for hiding this comment

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

Can we avoid using method overloading for this? This makes the code more difficult to maintain for very little gains I believe. I standard case/when would work perfectly fine here:

          values.each do |key, value|
            sanitized_value = case value
            when Field::Any, Model
              value
            when ::Enum
              value.to_s
            else
              next
            end

            sanitized_values[key.to_s] = value
          end

Comment on lines +1553 to +1564
values.each do |k, v|
case v
when Field::Any, DB::Model
update_hash[k.to_s] = v
when ::Enum
update_hash[k.to_s] = normalize_enum_update_value(k, v)
else
raise Errors::UnexpectedFieldValue.new(
"Value '#{v.inspect}' cannot be used in update queries"
)
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.

I am not convinced that we should introduce this type of logic at this level. The Query#update_with method already calls #to_db for each of the fields corresponding to the values specified as input. I would argue that we should try to reuse this as much as possible instead of replicating some of this logic at the set level (whose responsibility is mainly to enable the query set interface and to leave everything related to data preparation to the query abstraction).

Comment on lines +1694 to +1701
field = begin
M.get_field(field_name)
rescue Errors::UnknownField
nil
end
return value.to_s if field.nil? || !field.is_a?(Field::Enum)

field.as(Field::Enum).to_db(value).as(Field::Any)
Copy link
Member

Choose a reason for hiding this comment

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

Additionally, outside of relation fields, we should avoid making assumptions regarding the type of fields being manipulated. As such, we should not explicitly check that the manipulated field is an enum field, ideally.


localized_format_index = 0
fallback_format_index = 0
format = I18n.t("marten.schema.field.date.input_formats.#{localized_format_index}")
Copy link
Member

Choose a reason for hiding this comment

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

This can be removed from this PR (I believe this was already fixed in main).


localized_format_index = 0
fallback_format_index = 0
format = I18n.t("marten.schema.field.date_time.input_formats.#{localized_format_index}")
Copy link
Member

Choose a reason for hiding this comment

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

Same here.

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

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants