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

THREESCALE-9169: Upgrade to Ruby 3.1 #3847

Merged
merged 22 commits into from
Sep 19, 2024
Merged

THREESCALE-9169: Upgrade to Ruby 3.1 #3847

merged 22 commits into from
Sep 19, 2024

Conversation

mayorova
Copy link
Contributor

@mayorova mayorova commented Jul 11, 2024

What this PR does / why we need it:

Upgrading to Ruby 3.1

Which issue(s) this PR fixes

https://issues.redhat.com/browse/THREESCALE-9169

Verification steps

Everything should work :)

Special notes for your reviewer:

See comments inline.

Node is upgrade to v18, because v16 is very old and is out of maintenance since 2023, and apparently nothing breaks.

Related builder image upgrade (for CircleCI): 3scale/system-builder#38

NOTE: actually the builder image built from that PR above is not currently working, cause timeouts in cucumber tests.
The one that works forces Chrome version 126: 3scale/system-builder#41
It is available under tag quay.io/3scale/system-builder:stream8-ruby3.1-chrome126

Copy link
Contributor

@akostadinov akostadinov left a comment

Choose a reason for hiding this comment

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

Looks great, I was thinking to look at this and it's nice you posted it in draft phase.

I wonder though, shouldn't we first go to 3.0 to avoid any surprises from obsolete features in 3.1 that we could catch as deprecations with 3.0?

@@ -3,7 +3,7 @@
class AccountDecorator < ApplicationDecorator
delegate :display_name, :email, to: :admin_user, prefix: true

private
protected
Copy link
Contributor

Choose a reason for hiding this comment

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

Just curious what changed in ruby to require this

Copy link
Contributor Author

@mayorova mayorova Jul 12, 2024

Choose a reason for hiding this comment

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

Not Ruby, but draper gem upgrade (which was needed to support the newer Ruby version).
The issue was here: https://github.com/drapergem/draper/blob/v4.0.2/lib/draper/automatic_delegation.rb#L10-L26

In decorators we delegate all methods to the decorated object. But this version of the library only does that when there is no private method with the same name on the decorator. In this case, as admin_user was a private method on AccountDecorator, draper tried to call admin_user on superclass, but it was not there, so it was failing with:

ActionView::Template::Error (super: no superclass method `admin_user' for #<AccountDecorator:0x00007f8784266d18 @object=#<Account id: 11, org_name: "Testing" ...>
Did you mean?  admin_user_email):

So, I removed it from private_methods and now it works fine. Not sure it's the best solution though.

Copy link
Contributor

Choose a reason for hiding this comment

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

And wouldn't it be better to rename the private method on AccountDecorator? This tricks the object to respond to two methods with the same name. It feels wrong.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

respond to two methods

Why two methods?

Copy link
Contributor

@jlledom jlledom Jul 25, 2024

Choose a reason for hiding this comment

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

If I understood it correctly, there is an #admin_user method in AccountDecorator and another #admin_user method in Account. So AccountDecorator responds to one public #admin_user which delegates to Account and to a private #admin_user. Is that correct?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Because AccountDecorator had two ways to respond to admin_user, isn't that confusing?

I don't think it has 2 ways. The method defined in the AccountDecorator is the one that will be called when calling admin_user, then it's up the the implementation of this method where to send it further.

I think it's actually a common approach - decorator "decorates" the wrapped object (Account in this case) by adding some new methods or overriding others, but the decorator also responds to the methods of the wrapped object.
So, I think having the same method name is fine.

Whatever name, it's was private method, so it didn't matter.

Yeah, but it was failing exactly because it was private, so I made it non-private, and in fact, I have now also made it public, as I think it actually makes more sense.

If I call AccountDecorator#admin_user from inside AccountDecorator, which one is called? The private method in AccountDecorator or the public method in Account?

As I said above (because I didn't finish reading the comment before replying 😬 ) I believe the method (either private or public) in AccountDecorator is called always. As with inheritance. First the method inside the same class is checked, and only if not found, superclasses are checked (or wrapped objects in this case).

OK, so we're good now? 😄

Copy link
Contributor

Choose a reason for hiding this comment

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

Well, it makes no sense going on with the discussion when the confusing situation doesn't exist anymore. But... 😁

I think it's actually a common approach - decorator "decorates" the wrapped object (Account in this case) by adding some new methods or overriding others, but the decorator also responds to the methods of the wrapped object.

Was a private #admin_user overriding the public #admin_user from Account?. Two comments here:

  1. Can a private method override a public method in Ruby?, is that legal? Then the class would implement a different behavior for the same method depending of it being called from inside or outside. That's what I meant by "two ways to respond"
  2. This is no real inheritance because AccountDecorator is not a subclass of Account. The behavior is defined by drapper, so it was even more confusing. Apparently, they decided to not allow overriding public methods with private methods, and IMO they did right because that forced us to define our methods as public, which I think is the right approach.

Yeah, but it was failing exactly because it was private, so I made it non-private, and in fact, I have now also made it public, as I think it actually makes more sense.

Agreed

OK, so we're good now? 😄

I'll let this go because it's Friday... 😎

Copy link
Contributor Author

Choose a reason for hiding this comment

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

OK, I see, your point was not about only having the same method name, but rather having the same method name, BUT different visibility.

Yeah, I see your point. Indeed, it was a bit confusing, but now it's fixed :)

Copy link
Contributor

Choose a reason for hiding this comment

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

Just for completeness, you can't have two methods of same name in ruby with different visibility. You have just one. Private or not, it overrides the one in superclass. But then you can mark it private or protected or public for that matter in the sub-class. Not a good design though.

In this case this is not even a superclass but some kind of a wrapper. And obviously they decided it was a bad idea there too. Which likely so.

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks for the explanation @akostadinov

# TODO: Ruby 3 TEMPORARY HACK! Figure this out for liquid
# def controller
# @context.registers[:controller]
# end
Copy link
Contributor

Choose a reason for hiding this comment

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

What is the consequence of this method being removed?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Well, this is tricky. I just commented it out temporarily in order to be able to load the admin portal and find other issues 🙃

This needs a proper fix.

Basically, what the issue is is that I think this is supposed to be only loaded on the developer portal, where we have Liquid. But it was also loading in the admin portal, so each time any admin page was loaded, there was this error:

ActionView::Template::Error (undefined method `registers' for nil:NilClass

      @context.registers[:controller]
              ^^^^^^^^^^):
    1: - content_for :stylesheets do
    2:   = stylesheet_link_tag 'vendor/c3'
    3: 
    4: - content_for :javascripts do
    5:   = javascript_packs_with_chunks_tag 'dashboard'

Because we don't have @context here.

We're loading that helper here:

Rails.application.config.to_prepare do
# Hacks
ActionView::Helpers.send(:include, Liquid::UrlHelperHacks)

and I couldn't figure out yet how to load it only for the developer portal.

And in general, I don't quite understand how Liquid works, where @context is populated etc. So I left it for later.
If you have any ideas - please let me know!

Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe full backtrace will help identify where is it called from.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I ended up removing the whole thing 😬
Some comments about it here - #3847 (comment)

app/queries/new_accounts_query.rb Outdated Show resolved Hide resolved
@mayorova
Copy link
Contributor Author

mayorova commented Jul 12, 2024

I wonder though, shouldn't we first go to 3.0 to avoid any surprises from obsolete features in 3.1 that we could catch as deprecations with 3.0?

I didn't read all of that, but it seemed to me that the two versions are fully compatible, just that 3.1 add some extra features:
https://www.ruby-lang.org/en/news/2021/12/25/ruby-3-1-0-released/
https://rubyreferences.github.io/rubychanges/3.1.html

@akostadinov
Copy link
Contributor

akostadinov commented Jul 12, 2024

I didn't read all of that, but it seemed to me that the two versions are fully compatible, just that 3.1 add some extra features

Sounds reasonable. One more thing to consider though is https://bugs.ruby-lang.org/issues/18829

Seems like there are some issues with ppc64le arch. Just giving a heads up. Need to investigate that next week.

@mayorova mayorova force-pushed the ruby-3.1 branch 7 times, most recently from 2da5a34 to bf4f367 Compare July 19, 2024 09:55
@@ -108,8 +108,8 @@ def authenticated_token
@authenticated_token = domain_account.access_tokens.find_from_value(access_token) if access_token
end

def enforce_access_token_permission
PermissionEnforcer.enforce(authenticated_token, &Proc.new)
def enforce_access_token_permission(&block)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I am not sure the changes in this file are actually related to Ruby upgrade. I think it was just fixing some IDE style warnings.

@@ -464,20 +465,25 @@ GEM
with_env (= 1.1.0)
xml-simple (~> 1.1.9)
liquid (3.0.6)
listen (3.2.1)
listen (3.9.0)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

listen-3.2.1 requires ruby version >= 2.2.7, ~> 2.2, which is incompatible with the current version, ruby 3.1.4p223

@@ -670,8 +686,8 @@ GEM
redis-client (>= 0.17.0)
redis-client (0.21.1)
connection_pool
redis-namespace (1.7.0)
redis (>= 3.0.4)
redis-namespace (1.11.0)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

redis-namespace-1.7.0 requires ruby version ~> 2.4, which is incompatible with the current version, ruby 3.1.4p223

@@ -892,7 +919,7 @@ GEM
unf_ext (0.0.7.7)
unicode-display_width (2.3.0)
unicode_utils (1.4.0)
unicorn (5.4.1)
unicorn (6.1.0)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

unicorn-5.4.1 requires ruby version < 3.0, which is incompatible with the current version, ruby 3.1.4p223

Gemfile Outdated Show resolved Hide resolved
@@ -44,6 +42,8 @@ gem 'bcrypt', '~> 3.1.7'
gem 'oauth2', '~> 2.0'
gem 'open_id_authentication'

gem 'sorted_set', '~> 1.0'
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixing:

/home/dmayorov/.asdf/installs/ruby/3.1.4/lib/ruby/3.1.0/set/sorted_set.rb:4:in `rescue in <main>': The `SortedSet` class has been extracted from the `set` library. You must use the `sorted_set` gem or other alternatives. (RuntimeError)
/home/dmayorov/.asdf/installs/ruby/3.1.4/lib/ruby/gems/3.1.0/gems/bootsnap-1.16.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:17:in `require': cannot load such file -- sorted_set (LoadError)
/home/dmayorov/.asdf/installs/ruby/3.1.4/lib/ruby/gems/3.1.0/gems/bootsnap-1.16.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:17:in `require': cannot load such file -- oily_png (LoadError)

See ruby/set#2

@@ -158,7 +159,7 @@ gem 'html-pipeline'
gem 'ruby-openid'
gem 'slim-rails', '~> 3.2'

gem 'draper', '~> 3.1'
gem 'draper', '~> 4.0.2'
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixing:

/home/dmayorov/.asdf/installs/ruby/3.1.4/lib/ruby/gems/3.1.0/gems/activesupport-6.1.7.8/lib/active_support/core_ext/module/delegation.rb:173:in `delegate': Delegation needs a target. Supply a keyword argument 'to' (e.g. delegate :hello, to: :greeter). (ArgumentError)

4.0.2 is the first version with Ruby 3 compatibility: https://github.com/drapergem/draper/blob/master/CHANGELOG.md#402---2021-05-27

@@ -120,7 +120,8 @@ gem 'ts-datetime-delta', require: 'thinking_sphinx/deltas/datetime_delta'
gem 'will_paginate', '~> 3.3'
gem 'zip-zip', require: false

gem 'acts_as_tree'
# TODO: this gem seems a bit abandoned, consider getting rid of it
gem 'acts_as_tree', '~> 2.9.1'
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixing:

ActionView::Template::Error (undefined method `arity' for {:class_name=>"Metric", :primary_key=>"id", :foreign_key=>"parent_id", :counter_cache=>nil, :touch=>false, :inverse_of=>:children, :optional=>true}:Hash

      if scope && scope.arity == 0
                       ^^^^^^):
    1: #quick-start-container data-render-catalog=(active_menu == :quickstarts).to_s data-links=quickstarts_presenter.links

Version 2.9.1 adds Ruby 3 compatibility: https://github.com/amerine/acts_as_tree/releases/tag/v2.9.1

# Also, upgrading makes this test fail: SendUserInvitationWorkerTest#test_handles_errors
gem 'mail', '~> 2.7.1'
# TODO: verify if this test fails: SendUserInvitationWorkerTest#test_handles_errors
gem 'mail', '~> 2.8.1'
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixing

/home/dmayorov/.asdf/installs/ruby/3.1.4/lib/ruby/gems/3.1.0/gems/bootsnap-1.16.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:17:in `require': cannot load such file -- net/smtp (LoadError)

@@ -10,6 +10,10 @@ module Categorizable
end
end

def initialize(args = {})
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Support for Ruby 3.1 is added in rails_event_store version v2.4.0: https://github.com/RailsEventStore/rails_event_store/releases/tag/v2.4.0

But we are currently at 0.9.0... 🫠

Copy link
Contributor

Choose a reason for hiding this comment

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

Can't we update rails_event_store?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I am not sure, but it looks like a very big jump 🙃
Probably would involve some DB migrations. So maybe we can attempt to upgrade it (I think that would be nice), but I'd suggest to do it in another PR :)

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh, I didn't know that was so demanding. Surely if we do it it must be in another PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, at least these releases have some breaking changes and required DB migrations:
https://github.com/RailsEventStore/rails_event_store/releases/tag/v0.19.0
https://github.com/RailsEventStore/rails_event_store/releases/tag/v2.0.0

I'm not sure it's even possible to upgrade in one go... needs to be investigated.

Copy link
Contributor

Choose a reason for hiding this comment

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

I read this upgrade walkthrough [1] in the past and decided that upgrading it would be probably harder than replacing it. I don't think we want to have this event system. Hard to track it's logic and we have so many other approaches already.

But if anybody wants to...

[1] https://blog.arkency.com/update-rails-event-store-to-v1-dot-0-0-walkthrough/

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't mean to start a full-blown discussion on what to do with the event store, but...

Hard to track it's logic and we have so many other approaches already.

@akostadinov which approaches you are referring to?

Copy link
Contributor

Choose a reason for hiding this comment

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

I mean that we use many design patterns. hooks/callbacks, services, events, background jobs, and maybe more partially competing design patterns. IMO services is easier to maintain than events. FWIW on last f2f Hery expressed an opinion that in the long term services are easier to understand and maintain in the long run. That's what I meant. But yeah, open for discussion.

@@ -25,8 +25,8 @@ def check_creation_errors
# and not respond with pathetic error
raise ActiveRecord::RecordNotFound if @signup_result.errors[:plans].present?

@signup_result.user.errors.each do |attr, error|
@signup_result.account.errors.add(attr, error)
@signup_result.user.errors.each do |error|
Copy link
Contributor Author

Choose a reason for hiding this comment

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

DEPRECATION WARNING: Enumerating ActiveModel::Errors as a hash has been deprecated.
In Rails 6.1, `errors` is an array of Error objects,
therefore it should be accessed by a block with a single block
parameter like this:

person.errors.each do |error|
  attribute = error.attribute
  message = error.message
end

You are passing a block expecting two parameters,
so the old hash behavior is simulated. As this is deprecated,
this will result in an ArgumentError in Rails 7.0.

@@ -3,6 +3,6 @@
ActiveSupport::TestCase.class_eval do
include ActiveSupport::Testing::FileFixtures

self.fixture_path = Rails.root.join('test', 'fixtures')
self.file_fixture_path = self.fixture_path
self.fixture_path = Rails.root.join('test/fixtures')
Copy link
Contributor Author

Choose a reason for hiding this comment

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

DEPRECATION WARNING: Passing a path to `fixture_file_upload` relative to `fixture_path` is deprecated.
In Rails 7.0, the path needs to be relative to `file_fixture_path`.

Please modify the call from
`fixture_file_upload("wide.jpg")` to `fixture_file_upload("../../../test/fixtures/wide.jpg")`.
 (called from block (4 levels) in <main> at /home/dmayorov/Projects/3scale/porta/spec/acceptance/api/cms_file_spec.rb:24)

Copy link
Contributor

Choose a reason for hiding this comment

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

How this solves that warning? wasn't the path relative before?

Copy link
Contributor Author

@mayorova mayorova Jul 25, 2024

Choose a reason for hiding this comment

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

Sorry, I left the comment on the wrong line 🙃

In this file only Rubocop warnings are being fixed:

RuboCop: Please use `Rails.root.join('path/to')` instead. [Rails/FilePath]
RuboCop: Redundant `self` detected. [Style/RedundantSelf]

The actual fix for the deprecation warning is adding the line config.file_fixture_path = config.fixture_path in spec/rails_helper.rb 😅 (https://github.com/3scale/porta/pull/3847/files#diff-053aa3ea46cb7c6a649e0d0fc592ce729b66e1d44be475516fd58857ba695862R77)

I just checked this file to see why it was not giving warning for integration tests, and decided to fix the warnings along the way.

Copy link
Contributor

Choose a reason for hiding this comment

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

Nice, thanks for clarifying.

@@ -73,7 +73,7 @@ gem 'stripe', '~> 5.28.0' # we need the stripe gem because activemerchant can no
gem 'acts_as_list', '~> 0.9.17'
gem 'braintree', '~> 2.93'
gem 'bugsnag', '~> 6.26'
gem 'cancancan', '~> 3.0.0'
gem 'cancancan', '~> 3.6.0'
Copy link
Contributor Author

Choose a reason for hiding this comment

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

3.1.0 was the first version to fix keyword arguments: https://github.com/CanCanCommunity/cancancan/blob/develop/CHANGELOG.md#310

But going up to 3.6.0 seemed OK.

Gemfile Outdated
@@ -198,7 +198,7 @@ group :test do
gem 'fakefs', require: 'fakefs/safe'
gem 'launchy'
gem 'mechanize'
gem 'selenium-webdriver', '~> 3.142', require: false
gem 'selenium-webdriver', '~> 4.22.0', require: false
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I believe this was required after capybara upgrade to fix the issue:

Message:uninitialized constant Selenium::WebDriver::ShadowRoot

    when Selenium::WebDriver::Element, Selenium::WebDriver::ShadowRoot
                                                          ^^^^^^^^^^^^ (NameError)
/opt/ci/project/vendor/bundle/ruby/3.1.0/gems/capybara-3.40.0/lib/capybara/selenium/driver.rb:448:in `unwrap_script_result'

@mayorova mayorova force-pushed the ruby-3.1 branch 2 times, most recently from 82c4f99 to 63c62bb Compare July 22, 2024 10:58
module UrlHelperHacks
# This is the same as the original implementation, except the controller here is accessed
# through method, not variable. This way it's more hackable.
def current_page?(options)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Well, this is weird. I don't know honestly how and why that was needed 🤔 Well, the comment kind of explains it - apparently the only purpose is to take the controller from the #controller method rather than from the @controller variable.
But this implementation is from Rails v2 🙃 Recent versions don't actually rely on @controller, but on the #request method (see Rails 6.1 implementation).

An attempt to summarize the old and the new behavior:

  1. In master + Ruby 2.7 I didn't even manage to get into this method (either of the two methods in this module in fact). Not sure why, whether it's because of how the module is included or what. It always goes to the standard Ruby's current_page? method.

  2. In ruby-3.1 branch + Ruby 3.1 the #controller method is always called, both in the developer portal (where it was supposed to work, I think), and in the admin portal, and it breaks the flow in admin portal, because of the error:

undefined method `registers' for nil:NilClass

      @context.registers[:controller]
              ^^^^^^^^^^

Interestingly, removing this #controller method apparently doesn't break anything. Also, the #current_page? method from this module is also called in some pages. But I think this method is just way too outdated to keep it, so I've removed it also.

Copy link
Contributor

Choose a reason for hiding this comment

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

wow

@mayorova mayorova changed the title [WIP] THREESCALE-9169: Ruby 3.1 THREESCALE-9169: Upgrade to Ruby 3.1 Jul 22, 2024
@mayorova mayorova marked this pull request as ready for review July 22, 2024 14:17
The issue was caused by `draper` gem upgrade (which was a result of
upgrading Ruby to v3). The issue was here:
https://github.com/drapergem/draper/blob/v4.0.2/lib/draper/automatic_delegation.rb#L10-L26

In decorators we delegate all methods to the decorated object. But this version of the library
only does that when there is no private method with the same name on the decorator.
In this case, as `admin_user`  was a private method on AccountDecorator, draper tried to call
`admin_user `on superclass, but it was not there, so it was failing with:
```
ActionView::Template::Error (super: no superclass method `admin_user' for #<AccountDecorator:0x00007f8784266d18
  @object=#<Account id: 11, org_name: "Testing" ...> Did you mean? admin_user_email):
```

Removing it from `private_methods` fixed the issue.
This test caused multiple tests fail with:
```
ThreadError: deadlock; lock already owned by another fiber belonging to the same thread
```

This is fixed in Rails 7.0.6 and higher: rails/rails#46553
```
DEPRECATION WARNING: Passing a path to `fixture_file_upload` relative to `fixture_path` is deprecated.
In Rails 7.0, the path needs to be relative to `file_fixture_path`.

Please modify the call from
`fixture_file_upload("wide.jpg")` to `fixture_file_upload("../../../test/fixtures/wide.jpg")`.
 (called from block (4 levels) in <main> at /home/dmayorov/Projects/3scale/porta/spec/acceptance/api/cms_file_spec.rb:24)
```
akostadinov
akostadinov previously approved these changes Sep 18, 2024
Copy link
Contributor

@akostadinov akostadinov left a comment

Choose a reason for hiding this comment

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

Two small comments in case they are relevant. I think we are good to go!

yield csv
end
def generate(&block)
::CSV.generate(**csv_options, &block)
Copy link
Contributor

Choose a reason for hiding this comment

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

Now generate can be called without a block which would fail previously 🤔
I don't like allowing things that were not allowed previously although this looks pretty innocent.

@@ -5,7 +5,7 @@ class ActiveRecordEventRepository < RailsEventStoreActiveRecord::EventRepository
def build_event_entity(record)
return nil unless record

data = (record.data || {}).merge(
data = record.data.merge(
Copy link
Contributor

Choose a reason for hiding this comment

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

can't data be nil? In such case original version will not fail.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In the DB NULL values are permitted for the data column. But as this field is serialized/deserialized as YAML, when the object is instantiated, it appears that record.data is set to an empty hash, if the data column value is nil, so it seems fine.
I tested with the following:

class TestEvent < BaseEventStoreEvent
  def self.create
    new(
      metadata: {
        provider_id: 2
      }
     
    )
  end
end

event = TestEvent.create_and_publish!

event_from_repo = EventStore::Repository.find_event(event.event_id)

The data column is NULL for this event, but build_event_entity works fine.

I didn't know about this when reverting the change, but I thought - it used to work before, so it should still work.

In any case, we don't have any events in the code base that would have empty data, all have at least something.

validates :published, presence: true
validates :title, uniqueness: { :scope => [:provider_id], case_sensitive: true }

before_validation :publish_draft
Copy link
Contributor

Choose a reason for hiding this comment

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

Wouldn't it be better before_save? If I'm not mistaken, the draft will be published regardless of the template's validity.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The problem is that before_save runs after the validation. And if we don't fill published with a value before validation, the validation will fail 😬

Copy link
Contributor

Choose a reason for hiding this comment

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

All this changes are just for the sake of proper use of dig, are they not?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not really, the actual change is using (options) instead of (user_options:, **)

See this thread for more info: #3847 (comment)

akostadinov
akostadinov previously approved these changes Sep 19, 2024
Further refactor of pf_inline_alert
@mayorova mayorova merged commit 36c5ed9 into master Sep 19, 2024
29 of 33 checks passed
@mayorova mayorova deleted the ruby-3.1 branch September 19, 2024 12:15
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