8000 Refactor `Question.save_condition` by aaronskiba · Pull Request #3501 · DMPRoadmap/roadmap · GitHub
[go: up one dir, main page]

Skip to content

Refactor Question.save_condition #3501

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

Conversation

aaronskiba
Copy link
Contributor
@aaronskiba aaronskiba commented Apr 4, 2025

Changes proposed in this PR:

  • This PR refactors Question.save_condition via the following changes:
    • Refactor mapping of remove_data & option_list
      • This change uses .map to refactor/simplify the mapping of option_list and remove_data. It also removes the need for temporary arrays.
    • Refactor webhook_data validation and construction
      • This change adds the handle_webhook_data helper method
        • Helper method returns nil if any of the required webhook_data fields are absent. Else, it constructs and returns the webhook_data hash
      • Returning nil when any fields are absent enables us to simplify the if check that immediately follows (now line 240)
    • Refactor handling of c.option_list.empty?
      • Moved c.option_list.empty? immediately after c.option_list assignment to streamline logic.
      • This change reduces unnecessary processing of c.remove_data and c.webhook_data.
      • Isolating the c.option_list.empty? check also simplifies subsequent checks for c.remove_data.empty? and c.webhook_data.nil? later in the code.
    • Refactor option_list and remove_data handling
      • Moved logic for handling option_list and remove_data into separate helper methods (handle_option_list and handle_remove_data).
      • This simplifies our save_condition method and resolves some previously disabled rubocop offenses.

This change uses `.map` to refactor/simplify the mapping of `option_list` and `remove_data`. It also removes the needed for temporary arrays.
Refactored `save_condition` method via new `handle_webhook_data` helper method.
  - Helper method returns nil if any of the required webhook_data fields are absent. Else, it constructs and returns the webhook_data hash
  - Returning nil when any fields are absent enables us to simplify the if check that immediately follows (now line 240) to `if c.option_list.empty? || c.webhook_data.nil?`
- Overall, these changes simplify the `save_condition` method and even remove a previous rubocop offense.
- Moved `c.option_list.empty?` immediately after `c.option_list` assignment to streamline logic.
- This change reduces unnecessary processing of `c.remove_data` and `c.webhook_data`.
- Isolating the `c.option_list.empty?` check also simplifies subsequent checks for `c.remove_data.empty?` and c.webhook_data.nil?` later in the code.
- Moved logic for handling option_list and remove_data into separate helper methods (handle_option_list and handle_remove_data).
- This simplifies our `save_condition` method and resolves some previously disabled rubocop offenses.
@aaronskiba aaronskiba requested review from johnpinto1 and Copilot April 4, 2025 19:14
Copy link
@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot reviewed 1 out of 1 changed files in this pull request and generated no comments.

Comments suppressed due to low confidence (1)

app/models/question.rb:275

  • Consider adding unit tests for the new helper methods (handle_option_list, handle_remove_data, and handle_webhook_data) to ensure they handle all expected scenarios, including when the input arrays or required webhook fields are missing.
def handle_option_list(value, opt_map)

Copy link
github-actions bot commented Apr 4, 2025
1 Warning
⚠️ There are code changes, but no corresponding tests. Please include tests if this PR introduces any modifications in behavior. \n
Ignore this warning if the PR ONLY contains translation.io synced updates.

Generated by 🚫 Danger

Copy link
Contributor
@johnpinto1 johnpinto1 left a comment

Choose a reason for hiding this comment

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

739aad0 Approved
82984e2 Approved
49b9f7d Approved
115ea70 Approved

@aaronskiba I might be testing this f6a232b wrongly, but attempts at evaluating
always return true.

irb(main):088* web_hook = {
irb(main):089* 'webhook-name': 'fg',
irb(main):090* 'webhook-email':'x@example.com',
irb(main):091* 'webhook-subject':'SUBJECT',
irb(main):092* 'webhook-message': 'fgh'
irb(main):093> };
irb(main):094> puts web_hook
{:"webhook-name"=>"fg", :"webhook-email"=>"x@example.com", :"webhook-subject"=>"SUBJECT", :"webhook-message"=>"fgh"}
=> nil
irb(main):095> %w[webhook-name webhook-email webhook-subject webhook-message].any? { |key| web_hook[key].blank? }
=> true
irb(main):096* web_hook = {
irb(main):097* 'webhook-name': 'fg',
irb(main):098* 'webhook-email':'x@example.com',
irb(main):099* 'webhook-subject':'',
irb(main):100* 'webhook-message': 'fgh'
irb(main):101> };
irb(main):102> puts web_hook;
{:"webhook-name"=>"fg", :"webhook-email"=>"x@example.com", :"webhook-subject"=>"", :"webhook-message"=>"fgh"}
irb(main):103> %w[webhook-name webhook-email webhook-subject webhook-message].any? { |key| web_hook[key].blank? };
irb(main):104> %w[webhook-name webhook-email webhook-subject webhook-message].any? { |key| web_hook[key].blank? }
=> true

According to CodyAI one needs to convert the string key to a symbol key.to_sym. That seems to work.

%w[webhook-name webhook-email webhook-subject webhook-message].any? { |key| web_hook[key.to_sym].blank? }

%w[webhook-name webhook-email webhook-subject webhook-message].any? { |key| web_hook[key.to_sym].blank? }
irb(main):105> puts %w[webhook-name webhook-email webhook-subject webhook-message].any? { |key| web_hook[key].blank? }
true
=> nil
irb(main):106> puts %w[webhook-name webhook-email webhook-subject webhook-message].any? { |key| web_hook[key.to_sym].blank? }
true
=> nil
irb(main):107* web_hook = {
irb(main):108* 'webhook-name': 'fg',
irb(main):109* 'webhook-email':'x@example.com',
irb(main):110* 'webhook-subject':'SUBJECT',
irb(main):111* 'webhook-message': 'fgh'
irb(main):112> };
irb(main):113> puts %w[webhook-name webhook-email webhook-subject webhook-message].any? { |key| web_hook[key.to_sym].blank? }
false
=> nil
irb(main):114* web_hook = {
irb(main):115* 'webhook-name': 'fg',
irb(main):116* 'webhook-email':'x@example.com',
irb(main):117* 'webhook-subject':'',
irb(main):118* 'webhook-message': 'fgh'
irb(main):119> };
irb(main):120> puts %w[webhook-name webhook-email webhook-subject webhook-message].any? { |key| web_hook[key.to_sym].blank? }
true

@aaronskiba
Copy link
Contributor Author

739aad0 Approved 82984e2 Approved 49b9f7d Approved 115ea70 Approved

@aaronskiba I might be testing this f6a232b wrongly, but attempts at evaluating always return true.

irb(main):088* web_hook = { irb(main):089* 'webhook-name': 'fg', irb(main):090* 'webhook-email':'x@example.com', irb(main):091* 'webhook-subject':'SUBJECT', irb(main):092* 'webhook-message': 'fgh' irb(main):093> }; irb(main):094> puts web_hook {:"webhook-name"=>"fg", :"webhook-email"=>"x@example.com", :"webhook-subject"=>"SUBJECT", :"webhook-message"=>"fgh"} => nil irb(main):095> %w[webhook-name webhook-email webhook-subject webhook-message].any? { |key| web_hook[key].blank? } => true irb(main):096* web_hook = { irb(main):097* 'webhook-name': 'fg', irb(main):098* 'webhook-email':'x@example.com', irb(main):099* 'webhook-subject':'', irb(main):100* 'webhook-message': 'fgh' irb(main):101> }; irb(main):102> puts web_hook; {:"webhook-name"=>"fg", :"webhook-email"=>"x@example.com", :"webhook-subject"=>"", :"webhook-message"=>"fgh"} irb(main):103> %w[webhook-name webhook-email webhook-subject webhook-message].any? { |key| web_hook[key].blank? }; irb(main):104> %w[webhook-name webhook-email webhook-subject webhook-message].any? { |key| web_hook[key].blank? } => true

According to CodyAI one needs to convert the string key to a symbol key.to_sym. That seems to work.

%w[webhook-name webhook-email webhook-subject webhook-message].any? { |key| web_hook[key.to_sym].blank? }

%w[webhook-name webhook-email webhook-subject webhook-message].any? { |key| web_hook[key.to_sym].blank? } irb(main):105> puts %w[webhook-name webhook-email webhook-subject webhook-message].any? { |key| web_hook[key].blank? } true => nil irb(main):106> puts %w[webhook-name webhook-email webhook-subject webhook-message].any? { |key| web_hook[key.to_sym].blank? } true => nil irb(main):107* web_hook = { irb(main):108* 'webhook-name': 'fg', irb(main):109* 'webhook-email':'x@example.com', irb(main):110* 'webhook-subject':'SUBJECT', irb(main):111* 'webhook-message': 'fgh' irb(main):112> }; irb(main):113> puts %w[webhook-name webhook-email webhook-subject webhook-message].any? { |key| web_hook[key.to_sym].blank? } false => nil irb(main):114* web_hook = { irb(main):115* 'webhook-name': 'fg', irb(main):116* 'webhook-email':'x@example.com', irb(main):117* 'webhook-subject':'', irb(main):118* 'webhook-message': 'fgh' irb(main):119> }; irb(main):120> puts %w[webhook-name webhook-email webhook-subject webhook-message].any? { |key| web_hook[key.to_sym].blank? } true

Hi @johnpinto1, I'm definitely using more and more AI for these refactors myself, so I really appreciate the thorough testing. Here's a bit of a response to your observations:

irb(main):001> test_hash1 = {'key-1':'value'}
=> {:"key-1"=>"value"}
irb(main):002> test_hash2 = {'key-1' => 'value'}
=> {"key-1"=>"value"}

Even though both of the above used a string when defining key-1, it is a hash for test_hash1 and a string for test_hash2.

But what will be the type of the keys here?

  def handle_webhook_data(value)
    # return nil if any of the webhook fields are blank
    return if %w[webhook-name webhook-email webhook-subject webhook-message].any? { |key| value[key].blank? }

TEST 1 (All Fields Filled Out)

Screenshot from 2025-04-07 08-48-16

   291:   def handle_webhook_data(value)
   292:     # return nil if any of the webhook fields are blank
   293:     byebug
=> 294:     return if %w[webhook-name webhook-email webhook-subject webhook-message].any? { |key| value[key].blank? }
   295: 
   296:     # else return the constructed webhook_data hash
   297:     {
   298:       name: value['webhook-name'],
(byebug) value
{"question_option"=>["4854"], "action_type"=>"add_webhook", "number"=>"0", "webhook-name"=>"name", "webhook-email"=>"email@gmail.com", "webhook-subject"=>"subject", "webhook-message"=>"message"}
(byebug) %w[webhook-name webhook-email webhook-subject webhook-message].any? { |key| value[key].blank? }
false

TEST 2 (With a Field Missing)

Screenshot from 2025-04-07 08-49-39

   291:   def handle_webhook_data(value)
   292:     # return nil if any of the webhook fields are blank
   293:     byebug
=> 294:     return if %w[webhook-name webhook-email webhook-subject webhook-message].any? { |key| value[key].blank? }
   295: 
   296:     # else return the constructed webhook_data hash
   297:     {
   298:       name: value['webhook-name'],
(byebug) value
{"question_option"=>["4854"], "action_type"=>"add_webhook", "number"=>"0", "webhook-name"=>"name", "webhook-email"=>"email@gmail.com", "webhook-subject"=>"subject", "webhook-message"=>""}
(byebug) %w[webhook-name webhook-email webhook-subject webhook-message].any? { |key| value[key].blank? }
true

It appears to be behaving correctly when operating on the value arg passed to def handle_webhook_data

Copy link
Contributor
@johnpinto1 johnpinto1 left a comment

Choose a reason for hiding this comment

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

@aaronskiba Thanks for explaining why my test was not correct in this instance.

@aaronskiba aaronskiba merged commit c879520 into johnpinto1-updated-port-of-dmptool-conditional-questions-fix-for-rails7 Apr 7, 2025
8 checks passed
@aaronskiba aaronskiba deleted the aaron/refactor-question-save-condition branch April 7, 2025 20:18
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.

2 participants
0