From 27172a105f990b40ffe6b64b6e7c01a7a7f71eac Mon Sep 17 00:00:00 2001 From: Thomas von Deyen Date: Mon, 13 Oct 2025 12:51:11 +0200 Subject: [PATCH 1/6] Update Alchemy to 8.0 There are breaking and it is not worth supporting both in the same Gem version --- .github/workflows/ci.yml | 9 +- .github/workflows/lint.yml | 4 +- Gemfile | 4 +- alchemy-json_api.gemspec | 2 +- .../alchemy/json_api/element_serializer.rb | 2 +- spec/dummy/config/alchemy/page_layouts.yml | 2 - spec/dummy/config/initializers/alchemy.rb | 272 +++++++++++++++++- spec/dummy/config/initializers/devise.rb | 8 +- spec/dummy/config/initializers/dragonfly.rb | 1 - spec/dummy/config/webpacker.yml | 96 ------- 10 files changed, 281 insertions(+), 119 deletions(-) delete mode 100644 spec/dummy/config/webpacker.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6e12101..14dfc88 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,18 +13,11 @@ jobs: fail-fast: false matrix: alchemy_branch: - - 7.2-stable - - 7.3-stable - - 7.4-stable + - 8.0-stable ruby: - "3.2" - "3.3" - "3.4" - exclude: - - alchemy_branch: 7.2-stable - ruby: "3.4" - - alchemy_branch: 7.3-stable - ruby: "3.4" env: ALCHEMY_BRANCH: ${{ matrix.alchemy_branch }} steps: diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 4b1304f..d79d40f 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -10,14 +10,14 @@ jobs: Standard: runs-on: ubuntu-latest env: - ALCHEMY_BRANCH: 7.4-stable + ALCHEMY_BRANCH: 8.0-stable steps: - name: Checkout code uses: actions/checkout@v4 - name: Install Ruby and gems uses: ruby/setup-ruby@v1 with: - ruby-version: "3.1" + ruby-version: "3.4" bundler-cache: true - name: Lint Ruby files run: bundle exec standardrb diff --git a/Gemfile b/Gemfile index b28bba7..9f27374 100644 --- a/Gemfile +++ b/Gemfile @@ -17,9 +17,9 @@ gemspec # gem 'byebug', group: [:development, :test] gem "sqlite3", "~> 2.2" -alchemy_branch = ENV.fetch("ALCHEMY_BRANCH", "7.4-stable") +alchemy_branch = ENV.fetch("ALCHEMY_BRANCH", "8.0-stable") gem "alchemy_cms", github: "AlchemyCMS/alchemy_cms", branch: alchemy_branch -gem "alchemy-devise", github: "AlchemyCMS/alchemy-devise", branch: "7.4-stable" +gem "alchemy-devise", github: "AlchemyCMS/alchemy-devise", branch: alchemy_branch gem "rubocop", require: false gem "standard", "~> 1.25", require: false diff --git a/alchemy-json_api.gemspec b/alchemy-json_api.gemspec index d9e137c..8d8c001 100644 --- a/alchemy-json_api.gemspec +++ b/alchemy-json_api.gemspec @@ -18,7 +18,7 @@ Gem::Specification.new do |spec| spec.files = Dir["{app,config,db,lib}/**/*", "LICENSE", "Rakefile", "README.md"] - spec.add_dependency "alchemy_cms", [">= 7.2.0", "< 8"] + spec.add_dependency "alchemy_cms", [">= 8.0.0.b", "< 9"] spec.add_dependency "jsonapi.rb", [">= 1.6.0", "< 2.2"] spec.add_development_dependency "factory_bot" diff --git a/app/serializers/alchemy/json_api/element_serializer.rb b/app/serializers/alchemy/json_api/element_serializer.rb index 9624f31..d6b10c8 100644 --- a/app/serializers/alchemy/json_api/element_serializer.rb +++ b/app/serializers/alchemy/json_api/element_serializer.rb @@ -14,7 +14,7 @@ class ElementSerializer < BaseSerializer cache_options store: Rails.cache, namespace: "alchemy-jsonapi" attribute :deprecated do |element| - !!element.definition[:deprecated] + !!element.definition.deprecated end has_many :ingredients, diff --git a/spec/dummy/config/alchemy/page_layouts.yml b/spec/dummy/config/alchemy/page_layouts.yml index 6ef6402..cf00c56 100644 --- a/spec/dummy/config/alchemy/page_layouts.yml +++ b/spec/dummy/config/alchemy/page_layouts.yml @@ -25,12 +25,10 @@ autogenerate: [all_you_can_eat, right_column, left_column] - name: news - feed: true unique: true insert_elements_at: top elements: [headline, news] autogenerate: [news] - feed_elements: [news] - name: contact unique: true diff --git a/spec/dummy/config/initializers/alchemy.rb b/spec/dummy/config/initializers/alchemy.rb index 9809e36..d3d9e6c 100644 --- a/spec/dummy/config/initializers/alchemy.rb +++ b/spec/dummy/config/initializers/alchemy.rb @@ -1,3 +1,271 @@ -# frozen_string_literal: true +Alchemy.configure do |config| + # == This is the global Alchemy configuration file + # -Alchemy.signup_path = "/admin/pages" unless Rails.env.test? + # === Auto Log Out Time + # + # The amount of time of inactivity in minutes after which the user is kicked out of his current session. + # + # NOTE: This is only active in production environments + # + # config.auto_logout_time = 30 + + # === Page caching + # + # Enable/Disable page caching globally. + # + # NOTE: You can enable/disable page caching for single Alchemy::Definitions in the page_layout.yml file. + # + # config.cache_pages = true + + # === Sitemap + # + # Alchemy creates a XML, Google compatible, sitemap for you. + # + # The url is: http://your-domain.tld/sitemap.xml + # + # ==== Config Options: + # + # show_root [Boolean] # Show language root page in sitemap? + # show_flag [Boolean] # Enables the Checkbox in Page#update overlay. So your customer can set the visibility of pages in the sitemap. + # + # config.sitemap.tap do |sitemap| + # sitemap.show_root = true + # sitemap.show_flag = false + # end + + # === Default items per page in admin views + # + # In Alchemy's Admin, change how many items you would get shown per page by Kaminari + # config.items_per_page = 15 + + # === Preview window URL configuration + # + # By default Alchemy uses its internal page preview renderer, + # but you can configure it to be any URL instead. + # + # Basic Auth is supported. + # + # config.preview = { + # host: https://www.my-static-site.com + # auth: + # username: <%= ENV["BASIC_AUTH_USERNAME"] %%> + # password: <%= ENV["BASIC_AUTH_PASSWORD"] %%> + # } + # Preview config per site is supported as well. + # + # config.preview = { + # My site name: + # host: https://www.my-static-site.com + # auth: + # username: <%= ENV["BASIC_AUTH_USERNAME"] %%> + # password: <%= ENV["BASIC_AUTH_PASSWORD"] %%> + # } + + # === Picture rendering settings + # + # Alchemy uses Dragonfly to render images. Settings for image rendering are specific to elements and are defined in elements.yml + # + # Example: + # - name: some_element + # ingredients: + # - role: some_picture + # type: Picture + # settings: + # hint: true + # crop: true # turns on image cropping + # size: '500x500' # image will be cropped to this size + # + # See http://markevans.github.com/dragonfly for further info. + # + # ==== Global Options: + # + # output_image_quality [Integer] # If image gets rendered as JPG or WebP this is the quality setting for it. (Default 85) + # preprocess_image_resize [String] # Use this option to resize images to the given size when they are uploaded to the image library. Downsizing example: '1000x1000>' (Default nil) + # image_output_format [String] # The global image output format setting. (Default +original+) + # + # NOTE: You can always override the output format in the settings of your ingredients in elements.yml, I.E. {format: 'gif'} + # + # config.output_image_quality = 85 + # config.preprocess_image_resize = nil + # config.image_output_format = "original" + + # This is used by the seeder to create the default site. + # config.default_site.tap do |default_site| + # default_site.name = "Default Site" + # default_site.host = "*" + # end + + # This is the default language when seeding. + config.default_language.tap do |default_language| + default_language.code = "en" + default_language.name = "English" + # default_language.page_layout = "index" + # default_language.frontpage_name = "Index" + end + + # === Mailer Settings: + # + # To send emails via contact forms, you can create your form fields here and set which fields are to be validated. + # + # === Validating fields: + # + # Pass the field name as a symbol and a message_id (will be translated) to :validate_fields: + # + # ==== Options: + # + # page_layout_name: [String] # A +Alchemy::PageDefinition+ name. Used to render the contactform on a page with this layout. + # fields: [Array] # An Array of fieldnames. + # validate_fields: [Array] # An Array of fieldnames to be validated on presence. + # + # ==== Translating validation messages: + # + # The validation messages are passed through ::I18n.t so you can translate it in your language yml file. + # + # ==== Example: + # + # de: + # activemodel: + # attributes: + # alchemy/message: + # firstname: Vorname + # + # config.mailer.tap do |mailer| + # mailer.page_layout_name = "contact" + # mailer.forward_to_page = false + # mailer.mail_success_page = "thanks" + # mailer.mail_from = "your.mail@your-domain.com" + # mailer.mail_to = "your.mail@your-domain.com" + # mailer.subject = "A new contact form message" + # mailer.fields = ["salutation", "firstname", "lastname", "address", "zip", "city", "phone", "email", "message"] + # mailer.validate_fields = ["lastname", "email"] + # end + + # === User roles + # + # You can add own user roles. + # + # Further documentation for the auth system used please visit: + # + # https://github.com/ryanb/cancan/wiki + # + # ==== Translating User roles + # + # Userroles can be translated inside your the language yml file under: + # + # alchemy: + # user_roles: + # rolename: Name of the role + # + # config.user_roles = ["member", "author", "editor", "admin"] + + # === Uploader Settings + # + # upload_limit [Integer] # Set an amount of files upload limit of files which can be uploaded at once. Set 0 for unlimited. + # file_size_limit* [Integer] # Set a file size limit in mega bytes for a per file limit. + # + # *) Allow filetypes to upload. Pass * to allow all kind of files. + # + # config.uploader.tap do |uploader| + # uploader.upload_limit = 50 + # uploader.file_size_limit = 100 + # uploader.allowed_filetypes.tap do |file_types| + # file_types.alchemy_attachments = ["*"] + # file_types.alchemy_pictures = ["jpg", "jpeg", "gif", "png", "svg", "webp"] + # end + # end + + # === Link Target Options + # + # Values for the link target selectbox inside the page link overlay. + # The value gets attached as a data-link-target attribute to the link. + # + # == Example: + # + # Open all links set to overlay inside an jQuery UI Dialog Window. + # + # jQuery(a[data-link-target="overlay"]).dialog(); + # + # config.link_target_options = ["blank"] + + # === Format matchers + # + # Named aliases for regular expressions that can be used in various places. + # The most common use case is the format validation of ingredients, or attribute validations of your individual models. + # + # == Example: + # + # validates_format_of :url, with: Alchemy.config.format_matchers.url + # + # config.format_matchers.tap do |format| + # format.email = /\A[^@\s]+@([^@\s]+\.)+[^@\s]+\z/ + # format.url = /\A[a-z0-9]+([-.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?\z/ix + # format.link_url = /^(tel:|mailto:|\/|[a-z]+:\/\/)/ + # end + + # The layout used for rendering the +alchemy/admin/pages#show+ action. + # config.admin_page_preview_layout = "application" + + # The sizes for the preview size select in the page editor. + # config.page_preview_sizes = ["360", "640", "768", "1024", "1280", "1440"] + + # Enable full text search configuration + # + # It enables a searchable checkbox in the page form to toggle + # the searchable field. These information can used in a search + # plugin (e.g. https://github.com/AlchemyCMS/alchemy-pg_search). + # + # == Example + # + # # config/initializers/alchemy.rb + # Alchemy.config.page_searchable_checkbox = true + # + # config.show_page_searchable_checkbox = false + + # The storage adapter for Pictures and Attachments + # + config.storage_adapter = "dragonfly" + + # Additional JS modules to be imported in the Alchemy admin UI + # + # Be sure to also pin the modules with +Alchemy.importmap+. + # + # == Example + # + # Alchemy.importmap.pin "flatpickr/de", + # to: "https://ga.jspm.io/npm:flatpickr@4.6.13/dist/l10n/de.js" + # + # config.admin_js_imports << "flatpickr/de" + + # Additional importmaps to be included in the Alchemy admin UI + # + # Be sure to also pin modules with +Alchemy.importmap+. + # + # config.admin_importmaps.add( + # importmap_path: root.join("config/importmap.rb"), + # source_paths: [ + # root.join("app/javascript") + # ], + # name: "admin_extension" + # ) + + # Additional stylesheets to be included in the Alchemy admin UI + # config.admin_stylesheets.add("my_app/admin_extension") + + # Define page publish targets + # + # A publish target is a ActiveJob that gets performed + # whenever a user clicks the publish page button. + # + # Use this to trigger deployment hooks of external + # services in an asychronous way. + # + # config.publish_targets << "MyPublishJob" + + # Configure tabs in the link dialog + # + # With this configuration that tabs in the link dialog can be extended + # without overwriting or defacing the Admin Interface. + # + # config.link_dialog_tabs << "Acme::LinkTab" +end diff --git a/spec/dummy/config/initializers/devise.rb b/spec/dummy/config/initializers/devise.rb index 5e1f7e4..8708eb4 100644 --- a/spec/dummy/config/initializers/devise.rb +++ b/spec/dummy/config/initializers/devise.rb @@ -14,7 +14,7 @@ # confirmation, reset password and unlock tokens in the database. # Devise will use the `secret_key_base` as its `secret_key` # by default. You can change it below and use your own secret key. - # config.secret_key = 'a3e5b8e7089c0196c17e4b22a708f36d193da5d859e65ee6af46031f84c341eaa2a6050063d9294a415fc505c1591ff20a1c63babddb8cab9010a5ac711008a8' + # config.secret_key = '2feb8af0d2b0ffe7ae73a39502e5f4fbd2cc3a17a8d2d7a6abc706ab35ec0fc249a0801aa2d56956a6aaddfadf60f186447a2d79c7fa7a6a7997ee41b5f13874' # ==> Controller configuration # Configure the parent class to the devise controllers. @@ -24,7 +24,7 @@ # Configure the e-mail address which will be shown in Devise::Mailer, # note that it will be overwritten if you use your own mailer class # with default "from" parameter. - config.mailer_sender = Alchemy::Config.get(:mailer)['mail_from'] + config.mailer_sender = Alchemy.config.mailer.mail_from # Configure the class responsible to send e-mails. config.mailer = "Alchemy::Notifications" @@ -126,7 +126,7 @@ config.stretches = Rails.env.test? ? 1 : 12 # Set up a pepper to generate the hashed password. - # config.pepper = '73e2f6b111518b9a30148f5cc4d17a48b409d2cbce73f95e4349e845e40b77f53e5e2299bb7fc7cdc6fee147c282c6e57ec7921ea02d829c60f0dcd84ae84d43' + # config.pepper = '797fe652e0a115d80a704292969fe8e604ec5aa4bbcabff9dd44f2ef780c2eeeac926a2903fd12dad82f85862e53790cbae7184ca09b0aabfe28fc9f6b242251' # Send a notification to the original email when the user's email is changed. # config.send_email_changed_notification = false @@ -188,7 +188,7 @@ # ==> Configuration for :timeoutable # The time you want to timeout the user session without activity. After this # time the user will be asked for credentials again. Default is 30 minutes. - config.timeout_in = Rails.env.development? ? nil : Alchemy::Config.get(:auto_logout_time).minutes + config.timeout_in = Rails.env.development? ? nil : Alchemy.config.auto_logout_time.minutes # ==> Configuration for :lockable # Defines which strategy will be used to lock an account. diff --git a/spec/dummy/config/initializers/dragonfly.rb b/spec/dummy/config/initializers/dragonfly.rb index 514d77e..e132d1b 100644 --- a/spec/dummy/config/initializers/dragonfly.rb +++ b/spec/dummy/config/initializers/dragonfly.rb @@ -16,7 +16,6 @@ Dragonfly.app(:alchemy_pictures).configure do dragonfly_url nil plugin :imagemagick - plugin :svg secret "976ee38cf5e6d65dbf58f1d355825ba33239ab7a76a432818cd592526e9c78b5" url_format "/pictures/:job/:name.:ext" diff --git a/spec/dummy/config/webpacker.yml b/spec/dummy/config/webpacker.yml deleted file mode 100644 index 8581ac0..0000000 --- a/spec/dummy/config/webpacker.yml +++ /dev/null @@ -1,96 +0,0 @@ -# Note: You must restart bin/webpack-dev-server for changes to take effect - -default: &default - source_path: app/javascript - source_entry_path: packs - public_root_path: public - public_output_path: packs - cache_path: tmp/cache/webpacker - check_yarn_integrity: false - webpack_compile_output: true - - # Additional paths webpack should lookup modules - # ['app/assets', 'engine/foo/app/assets'] - resolved_paths: [] - - # Reload manifest.json on all requests so we reload latest compiled packs - cache_manifest: false - - # Extract and emit a css file - extract_css: false - - static_assets_extensions: - - .jpg - - .jpeg - - .png - - .gif - - .tiff - - .ico - - .svg - - .eot - - .otf - - .ttf - - .woff - - .woff2 - - extensions: - - .mjs - - .js - - .sass - - .scss - - .css - - .module.sass - - .module.scss - - .module.css - - .png - - .svg - - .gif - - .jpeg - - .jpg - -development: - <<: *default - compile: true - - # Verifies that correct packages and versions are installed by inspecting package.json, yarn.lock, and node_modules - check_yarn_integrity: true - - # Reference: https://webpack.js.org/configuration/dev-server/ - dev_server: - https: false - host: localhost - port: 3035 - public: localhost:3035 - hmr: false - # Inline should be set to true if using HMR - inline: true - overlay: true - compress: true - disable_host_check: true - use_local_ip: false - quiet: false - pretty: false - headers: - 'Access-Control-Allow-Origin': '*' - watch_options: - ignored: '**/node_modules/**' - - -test: - <<: *default - compile: true - - # Compile test packs to a separate directory - public_output_path: packs-test - -production: - <<: *default - - # Production depends on precompilation of packs prior to booting for performance. - compile: false - - # Extract and emit a css file - extract_css: true - - # Cache manifest.json for performance - cache_manifest: true From 4074439fe24d925ec2eb111b0f584b481d1d7f5c Mon Sep 17 00:00:00 2001 From: Thomas von Deyen Date: Tue, 18 Nov 2025 16:47:53 +0100 Subject: [PATCH 2/6] Add propshaft gem We need an asset pipeline for the dummy app. Signed-off-by: Thomas von Deyen --- Gemfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Gemfile b/Gemfile index 9f27374..428aa55 100644 --- a/Gemfile +++ b/Gemfile @@ -24,3 +24,5 @@ gem "alchemy-devise", github: "AlchemyCMS/alchemy-devise", branch: alchemy_branc gem "rubocop", require: false gem "standard", "~> 1.25", require: false gem "pry-byebug" + +gem "propshaft", "~> 1.3" From cc80805a62281558b4c49b4e915112a506198740 Mon Sep 17 00:00:00 2001 From: Thomas von Deyen Date: Tue, 18 Nov 2025 16:49:19 +0100 Subject: [PATCH 3/6] Fix config stubbing for Alchemy 8.0 It has changed from positional key and value arguments to a config hash. Signed-off-by: Thomas von Deyen --- spec/requests/alchemy/json_api/admin/layout_pages_spec.rb | 2 +- spec/requests/alchemy/json_api/admin/pages_spec.rb | 2 +- spec/requests/alchemy/json_api/pages_spec.rb | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/spec/requests/alchemy/json_api/admin/layout_pages_spec.rb b/spec/requests/alchemy/json_api/admin/layout_pages_spec.rb index c93dc69..23f515a 100644 --- a/spec/requests/alchemy/json_api/admin/layout_pages_spec.rb +++ b/spec/requests/alchemy/json_api/admin/layout_pages_spec.rb @@ -107,7 +107,7 @@ context "with caching enabled" do before do allow(Rails.application.config.action_controller).to receive(:perform_caching) { true } - stub_alchemy_config(:cache_pages, true) + stub_alchemy_config(cache_pages: true) end it "sets cache headers" do diff --git a/spec/requests/alchemy/json_api/admin/pages_spec.rb b/spec/requests/alchemy/json_api/admin/pages_spec.rb index e3aba0a..d34ed8a 100644 --- a/spec/requests/alchemy/json_api/admin/pages_spec.rb +++ b/spec/requests/alchemy/json_api/admin/pages_spec.rb @@ -30,7 +30,7 @@ context "with caching enabled" do before do allow(Rails.application.config.action_controller).to receive(:perform_caching) { true } - stub_alchemy_config(:cache_pages, true) + stub_alchemy_config(cache_pages: true) end it "sets cache headers" do diff --git a/spec/requests/alchemy/json_api/pages_spec.rb b/spec/requests/alchemy/json_api/pages_spec.rb index 72bb181..892f774 100644 --- a/spec/requests/alchemy/json_api/pages_spec.rb +++ b/spec/requests/alchemy/json_api/pages_spec.rb @@ -38,7 +38,7 @@ context "with caching enabled" do before do allow(Rails.application.config.action_controller).to receive(:perform_caching) { true } - stub_alchemy_config(:cache_pages, true) + stub_alchemy_config(cache_pages: true) end it "sets public cache headers" do @@ -229,7 +229,7 @@ context "with caching enabled" do before do allow(Rails.application.config.action_controller).to receive(:perform_caching) { true } - stub_alchemy_config(:cache_pages, true) + stub_alchemy_config(cache_pages: true) end it "sets public cache headers of latest published page" do @@ -384,7 +384,7 @@ context "with caching enabled" do before do allow(Rails.application.config.action_controller).to receive(:perform_caching) { true } - stub_alchemy_config(:cache_pages, true) + stub_alchemy_config(cache_pages: true) end it "sets constant etag" do From adb950a6c931aeebcffc36ca17856529fca553b9 Mon Sep 17 00:00:00 2001 From: Thomas von Deyen Date: Tue, 18 Nov 2025 16:50:13 +0100 Subject: [PATCH 4/6] Fix restricted pages max age expectation Alchemy 8.0 disables caching for restricted pages and now returns a max-age of 0. Signed-off-by: Thomas von Deyen --- spec/requests/alchemy/json_api/pages_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/requests/alchemy/json_api/pages_spec.rb b/spec/requests/alchemy/json_api/pages_spec.rb index 892f774..8533928 100644 --- a/spec/requests/alchemy/json_api/pages_spec.rb +++ b/spec/requests/alchemy/json_api/pages_spec.rb @@ -101,7 +101,7 @@ it "sets private cache headers" do get alchemy_json_api.page_path(page) - expect(response.headers["Cache-Control"]).to eq("max-age=600, private, must-revalidate") + expect(response.headers["Cache-Control"]).to eq("max-age=0, private, must-revalidate") end end @@ -293,7 +293,7 @@ it "sets private cache headers" do get alchemy_json_api.pages_path - expect(response.headers["Cache-Control"]).to eq("max-age=600, private, must-revalidate") + expect(response.headers["Cache-Control"]).to eq("max-age=0, private, must-revalidate") end end From fed72f4930f8ef3f199c792754235c929c0a1279 Mon Sep 17 00:00:00 2001 From: Thomas von Deyen Date: Tue, 18 Nov 2025 17:12:23 +0100 Subject: [PATCH 5/6] Fix ingredient picture serializer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Do not prepend image to file mime type. Alchemy 8 now returns the proper mime type. Also the picture factory does not allow anymore to pass the file size. Let’s use the size from the actual image used in the factory. Signed-off-by: Thomas von Deyen --- .../alchemy/json_api/ingredient_picture_serializer.rb | 2 +- .../alchemy/json_api/ingredient_picture_serializer_spec.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/serializers/alchemy/json_api/ingredient_picture_serializer.rb b/app/serializers/alchemy/json_api/ingredient_picture_serializer.rb index 62ae44f..0a1291e 100644 --- a/app/serializers/alchemy/json_api/ingredient_picture_serializer.rb +++ b/app/serializers/alchemy/json_api/ingredient_picture_serializer.rb @@ -72,7 +72,7 @@ class IngredientPictureSerializer < BaseSerializer end attribute :image_mime_type do |ingredient| - "image/#{ingredient.picture.image_file_format}" + ingredient.picture.image_file_format end attribute :image_file_size do |ingredient| diff --git a/spec/serializers/alchemy/json_api/ingredient_picture_serializer_spec.rb b/spec/serializers/alchemy/json_api/ingredient_picture_serializer_spec.rb index 56d610a..30bec09 100644 --- a/spec/serializers/alchemy/json_api/ingredient_picture_serializer_spec.rb +++ b/spec/serializers/alchemy/json_api/ingredient_picture_serializer_spec.rb @@ -12,7 +12,7 @@ ) end - let(:picture) { FactoryBot.create(:alchemy_picture, image_file_size: 301) } + let(:picture) { FactoryBot.create(:alchemy_picture) } subject(:serializer) { described_class.new(ingredient) } @@ -27,7 +27,7 @@ expect(subject[:image_name]).to eq("image") expect(subject[:image_file_name]).to eq("image.png") expect(subject[:image_mime_type]).to eq("image/png") - expect(subject[:image_file_size]).to eq(301) + expect(subject[:image_file_size]).to eq(70) expect(subject[:image_dimensions]).to eq(width: 1, height: 1) end From 005e828acc593f6687649cf28948398b8ba77a3e Mon Sep 17 00:00:00 2001 From: Thomas von Deyen Date: Tue, 18 Nov 2025 17:13:35 +0100 Subject: [PATCH 6/6] Fix ingredient serializer specs The factories now need to create the attachment. Stubbing does not work anymore with Alchemy 8 and its attachment adapters. Signed-off-by: Thomas von Deyen --- .../alchemy/json_api/ingredient_audio_serializer_spec.rb | 2 +- .../alchemy/json_api/ingredient_file_serializer_spec.rb | 2 +- .../alchemy/json_api/ingredient_video_serializer_spec.rb | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/serializers/alchemy/json_api/ingredient_audio_serializer_spec.rb b/spec/serializers/alchemy/json_api/ingredient_audio_serializer_spec.rb index 22f56cf..6639621 100644 --- a/spec/serializers/alchemy/json_api/ingredient_audio_serializer_spec.rb +++ b/spec/serializers/alchemy/json_api/ingredient_audio_serializer_spec.rb @@ -4,7 +4,7 @@ RSpec.describe Alchemy::JsonApi::IngredientAudioSerializer do let(:element) { FactoryBot.build_stubbed(:alchemy_element) } - let(:attachment) { FactoryBot.build_stubbed(:alchemy_attachment) } + let(:attachment) { FactoryBot.create(:alchemy_attachment) } let(:ingredient) do Alchemy::Ingredients::Audio.new( role: "audio", diff --git a/spec/serializers/alchemy/json_api/ingredient_file_serializer_spec.rb b/spec/serializers/alchemy/json_api/ingredient_file_serializer_spec.rb index fbbc29a..317b234 100644 --- a/spec/serializers/alchemy/json_api/ingredient_file_serializer_spec.rb +++ b/spec/serializers/alchemy/json_api/ingredient_file_serializer_spec.rb @@ -4,7 +4,7 @@ RSpec.describe Alchemy::JsonApi::IngredientFileSerializer do let(:ingredient) { FactoryBot.build_stubbed(:alchemy_ingredient_file, title: "File", css_class: "custom") } - let(:attachment) { FactoryBot.build_stubbed(:alchemy_attachment) } + let(:attachment) { FactoryBot.create(:alchemy_attachment) } subject(:serializer) { described_class.new(ingredient) } diff --git a/spec/serializers/alchemy/json_api/ingredient_video_serializer_spec.rb b/spec/serializers/alchemy/json_api/ingredient_video_serializer_spec.rb index 6a2b3ff..76a95dd 100644 --- a/spec/serializers/alchemy/json_api/ingredient_video_serializer_spec.rb +++ b/spec/serializers/alchemy/json_api/ingredient_video_serializer_spec.rb @@ -4,7 +4,7 @@ RSpec.describe Alchemy::JsonApi::IngredientVideoSerializer do let(:element) { FactoryBot.build_stubbed(:alchemy_element) } - let(:attachment) { FactoryBot.build_stubbed(:alchemy_attachment) } + let(:attachment) { FactoryBot.create(:alchemy_attachment) } let(:ingredient) do Alchemy::Ingredients::Video.new( role: "video",