Skip to content
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

fix: actions and field hydration #1992

Merged
merged 3 commits into from
Oct 31, 2023
Merged

Conversation

Paul-Bob
Copy link
Contributor

@Paul-Bob Paul-Bob commented Oct 25, 2023

Description

Fixes #1946

This pull request addresses primarily two key issues: the class attributes for actions and the field hydration method.

Action class attributes

Relying on class attributes for actions is not convenient since undesired old values can remain populated on a new instance.

Field Hydration Method

The existing code made it impossible to hydrate the field with nil values, resulting in undesired behavior. For instance, in cases where a field within an action relied on the @record via a default Proc, it would correctly receive the default value when executed in a show view. However, when executed in an index view, the field attempted to hydrate with model: nil, yet the prior model would remain hydrated, causing the value to be fetched incorrectly.

ActionModel removed

ActionModel was not being used only to pass it as model on form_with helper, and I think that was unecessary.

Checklist:

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • I have added tests that prove my fix is effective or that my feature works

Manual review steps

  1. Create an action with several fields that have the default value as Proc reling on the @record
    Example:
class ReleaseFish < Avo::BaseAction
  field :option_a, as: :boolean, default: -> { @record&.foo? }
  field :option_b, as: :boolean, default: -> { @record&.foo? }
  field :option_c, as: :boolean, default: -> { @record&.foo? }

  def handle(...)
    succeed ":)"
  end
end
  1. Define the method on the model
    Example:
  def foo?
    true
  end
  1. Register the action on a resource
  2. Go to that resource index page
  3. Select 2 records
  4. Run the action
  5. Notice that all fields are false since @record is blank
  6. Go to one record show view
  7. Run the action
  8. Notice that all fields are true since @record is setted ( and the default proc is running with @record properly hydrated on all executions )
  9. Return to index and run action after selecting 2 records
  10. Notice the same as step 7 (Prior this commit the fields would still hydrated with the @record from the show view since was impossible to hydrate with nil values)

Manual reviewer: please leave a comment with output from the test if that's the case.

@Paul-Bob Paul-Bob added the Fix label Oct 25, 2023
@Paul-Bob Paul-Bob self-assigned this Oct 25, 2023
@codeclimate
Copy link

codeclimate bot commented Oct 25, 2023

Code Climate has analyzed commit e9ec6f3 and detected 0 issues on this pull request.

View more on Code Climate.

@Paul-Bob Paul-Bob marked this pull request as draft October 25, 2023 07:59
@Paul-Bob Paul-Bob marked this pull request as ready for review October 25, 2023 16:59
Comment on lines -105 to +113
@resource = resource if resource.present?
@action = action if action.present?
@user = user if user.present?
@panel_name = panel_name if panel_name.present?
def hydrate(**kwargs)
# List of permitted keyword argument keys as symbols
permited_kwargs_keys = %i[model resource action view panel_name user]

# Check for unrecognized keys
unrecognized_keys = kwargs.keys - permited_kwargs_keys
raise ArgumentError, "Unrecognized argument(s): #{unrecognized_keys.join(', ')}" if unrecognized_keys.any?

# Set instance variables with provided values
kwargs.each do |key, value|
instance_variable_set("@#{key}", value)
end
Copy link
Collaborator

Choose a reason for hiding this comment

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

why the refactor here? it feels difficult to understand at a glance

Copy link
Contributor Author

@Paul-Bob Paul-Bob Oct 30, 2023

Choose a reason for hiding this comment

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

From PR description:

The existing code made it impossible to hydrate the field with nil values, resulting in undesired behavior. For instance, in cases where a field within an action relied on the @record via a default Proc, it would correctly receive the default value when executed in a show view. However, when executed in an index view, the field attempted to hydrate with model: nil, yet the prior model would remain hydrated, causing the value to be fetched incorrectly.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

What this does is if we use hydrate(model: nil) will assign @model = nil without touching the other variables... With the old code @model = model if model.present? since @model.present? == false the @model will keep the last assigned model even if we want to force hydrate it to nil...

Comment on lines +58 to +61
@model = model
@resource = resource
@user = user
@view = view
Copy link
Collaborator

Choose a reason for hiding this comment

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

Pfff. what a good fix!
THanks!

@@ -16,7 +16,6 @@ def show
@view = :new

@resource.hydrate(model: @model, view: @view, user: _current_user, params: params)
@model = ActionModel.new @action.get_attributes_for_action
Copy link
Collaborator

Choose a reason for hiding this comment

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

Not sure that this is the right decision.
I can't remember why, but at some point I know for a fact that it wasn't the right decision to use the @model.
Let's talk about it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Tests are not failing, also tested it intensively manually and everything works as expected

Copy link
Collaborator

@adrianthedev adrianthedev left a comment

Choose a reason for hiding this comment

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

Ok, let's merge it but let's keep an eye on it and mention something in the upgrade guide that we changed something internal and if they see anything off, they should reach out to us.

@Paul-Bob
Copy link
Contributor Author

Ok, let's merge it but let's keep an eye on it and mention something in the upgrade guide that we changed something internal and if they see anything off, they should reach out to us.

avo-hq/docs.avohq.io#127

@Paul-Bob Paul-Bob merged commit f7acbe4 into main Oct 31, 2023
12 of 13 checks passed
@Paul-Bob Paul-Bob deleted the fix/actions_and_field_hydration branch October 31, 2023 13:53
Copy link
Contributor

This PR has been merged into main. The functionality will be available in the next release.

Please check the release guide for more information.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

The fix for #1865 has broken default procs on custom actions
2 participants