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

Replace "some" default_value_for usage #22901

Merged
merged 8 commits into from
Feb 20, 2024

Conversation

jrafanie
Copy link
Member

@jrafanie jrafanie commented Feb 15, 2024

tldr; I think these are mostly safe changes that gets us closer to not depending on default_value_for. There's more to do but we can tackle that later if we really want to not use it anymore.

From research in upgrading default_value_for, it seems reasonable to replace it and not have to deal with getting this gem to work with rails as we upgrade. Currently, the gem's master branch supports rails 7 but hasn't been released so we need to ride master to work with rails 7 or fork it.

I've found the attributes API is mostly a replacement but it is different than default_value_for in the following ways:

  1. You can't override the getter/setter methods for the attribute in the same way you could with this gem. I think this revolves around how it's hard to detect if the super method's return is nil ({} serialize as hash attributes) explicitly or coming from the defaults from rails. I suspect there's a way to do it correctly but it's less obvious.
  2. The default value block format doesn't yield the instance, so you can't derive defaults based on the current instance. We definitely use this and the remaining usages are those.
  3. There doesn't seem to be a way to set multiple default values all at once. You have to set them individually. I don't think we use this feature.
  4. Default values make new objects look changed, unlike default_value_for.
  5. Attributes API default value doesn't support allow_nil: false so if a nil is provided as a value for an attribute, the default value will not be used. NOTE: I don't see much usage of this.

EDIT:

This PR avoids the more complicated changes where we used a block and the corresponding instance in the block. The remaining ones in core should probably be done in a followup PR. Either way, we can choose to keep default_value_for, but I thought it made sense to switch to vanilla rails for the more basic cases. This is what remains in core (note, there's also usage in providers/plugins):

app/models/miq_provision_request.rb:  default_value_for(:source_id)    { |r| r.get_option(:src_vm_id) || r.get_option(:source_id) }
app/models/miq_request.rb:  default_value_for(:message)       { |r| "#{r.class::TASK_DESCRIPTION} - Request Created" }
app/models/miq_request.rb:  default_value_for(:request_type)  { |r| r.request_types.first }
app/models/miq_retire_request.rb:  default_value_for(:source_id)    { |r| r.get_option(:src_id) }
app/models/service_reconfigure_request.rb:  default_value_for(:source_id)    { |r| r.get_option(:src_id) }
app/models/service_template.rb:  default_value_for(:generic_subtype) { |st| 'custom' if st.prov_type == 'generic' }
app/models/service_template_provision_request.rb:  default_value_for(:source_id)    { |r| r.get_option(:src_id) }
app/models/vm_retire_request.rb:  default_value_for(:source_id)    { |r| r.get_option(:src_ids) }

after_create :audit_creation
after_destroy :reload_all_server_settings, :audit_deletion
after_save :reload_all_server_settings
Copy link
Member Author

Choose a reason for hiding this comment

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

the cop wanted these sorted by their order... it's only the after_validation that's new

@jrafanie jrafanie changed the title [WIP] Replace default_value_for usage Replace default_value_for usage Feb 16, 2024
@jrafanie jrafanie changed the title Replace default_value_for usage Replace "some" default_value_for usage Feb 16, 2024
@jrafanie jrafanie mentioned this pull request Feb 16, 2024
@@ -75,7 +73,7 @@ def tz_or_default(default_tz = DEFAULT_TZ)
end

def days
profile[:days]
profile.fetch(:days, ALL_DAYS)
Copy link
Member

@kbrock kbrock Feb 19, 2024

Choose a reason for hiding this comment

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

attribute :days, :default => ALL_DAYS

Is there a reason to not just set the default on this attribute?

the default_value overriding what comes back from the database (vs creating the object) is a little suspect. Glad we are getting rid of this.

Do we want to db migrate profiles and set ALL_DAYS for time profiles with no :days in the hash?

Copy link
Member Author

Choose a reason for hiding this comment

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

I believe I tried that and existing tests failed because it's expecting this hash structure on the getter since it's done on the setter. I 100% agree with the idea of migrating this out and simplifying it. I don't know why it was done this way.

the default_value overriding what comes back from the database (vs creating the object) is a little suspect. Glad we are getting rid of this.

Good point. Let me check into it. most of the defaults were to set it if it's not set. We probably don't have good tests if I was able to ignore the value in the database. I think you found a bug.

Copy link
Member Author

Choose a reason for hiding this comment

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

Ok, I took a look. I think this is fine for now. I agree, we should stop storing the days/hours in the profile column.

@kbrock kbrock self-assigned this Feb 19, 2024
@kbrock
Copy link
Member

kbrock commented Feb 19, 2024

Still think using default for the database (in a migration) is a good alternative for these.

But keeping this in ruby does have its advantages

Comment on lines -17 to +19
def enabled=(value)
return if enabled == value

super
$audit_log.info("Blacklisted event [#{event_name}] for provider [#{provider_model}] with ID [#{ems_id}] had enabled changed to #{value} by user [#{self.class.current_userid}]")
def log_enabling
$audit_log.info("Blacklisted event [#{event_name}] for provider [#{provider_model}] with ID [#{ems_id}] had enabled changed to #{enabled} by user [#{self.class.current_userid}]")
Copy link
Member

Choose a reason for hiding this comment

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

  1. I really like the new solution here
  2. Do we need this audit trail?
  3. Can you add new_record? here? (maybe put a byebug in this method and create a new record - see if it goes in here. I worry seeding will produce a slew of these)

Copy link
Member Author

Choose a reason for hiding this comment

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

yeah, I'll check

Copy link
Member Author

Choose a reason for hiding this comment

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

Ok, it has the same exact behavior as before.

Seed with empty db... messages showing it was created, see audit_creation, then, became enabled. I'll add a check to change the behavior to only do it unless new_record?. I agree, it was a bug before.

Copy link
Member Author

@jrafanie jrafanie Feb 20, 2024

Choose a reason for hiding this comment

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

pushed change to skip if new_record? and added tests

@@ -3,7 +3,7 @@
class Endpoint < ApplicationRecord
belongs_to :resource, :polymorphic => true

default_value_for :verify_ssl, OpenSSL::SSL::VERIFY_PEER
attribute :verify_ssl, :default => OpenSSL::SSL::VERIFY_PEER
Copy link
Member

Choose a reason for hiding this comment

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

FYI: OpenSSL::SSL::VERIFY_PEER == 1

@jrafanie jrafanie force-pushed the drop_default_value_for branch 2 times, most recently from 3ece4e3 to e3efcc0 Compare February 20, 2024 18:35
@miq-bot
Copy link
Member

miq-bot commented Feb 20, 2024

Checked commits jrafanie/manageiq@5b5e927~...48e1183 with ruby 2.7.8, rubocop 1.56.3, haml-lint 0.51.0, and yamllint
51 files checked, 3 offenses detected

spec/lib/extensions/ar_yaml_spec.rb

@jrafanie
Copy link
Member Author

@kbrock pushed minor changes. I think you raise good questions for followup. I think the changes here are minimized to avoid changing behavior without using default_value_for.

@@ -3,7 +3,7 @@
describe "#uniqueness_when_changed" do
it "queries for a new record" do
alert = FactoryBot.build(:miq_alert)
expect { alert.valid? }.to make_database_queries(:count => 1)
expect { alert.valid? }.to make_database_queries(:count => 2)
Copy link
Member

@kbrock kbrock Feb 20, 2024

Choose a reason for hiding this comment

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

sigh

Not thrilled about getting a changed event for a default value.
I had thought that this changed the base metadata (so it acted as if the database specified the default value), but this suggests that is not true.

Copy link
Member Author

Choose a reason for hiding this comment

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

haha, yup... default_value_for masked changes... we can do the same but I was hoping we didn't need to.

@kbrock kbrock merged commit c773b2b into ManageIQ:master Feb 20, 2024
8 checks passed
@kbrock kbrock added the rails7 label Feb 20, 2024
@jrafanie jrafanie deleted the drop_default_value_for branch February 20, 2024 21:07
jrafanie added a commit to jrafanie/manageiq that referenced this pull request Feb 29, 2024
…value_for"

This reverts commit c773b2b, reversing
changes made to bb72015.
agrare added a commit that referenced this pull request Feb 29, 2024
Revert "Merge pull request #22901 from jrafanie/drop_default_value_for"
Fryguy pushed a commit that referenced this pull request Mar 1, 2024
Revert "Merge pull request #22901 from jrafanie/drop_default_value_for"

(cherry picked from commit 340776c)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants