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

ActiveModel::Errors support #44

Open
calebuharrison opened this issue Oct 4, 2024 · 1 comment
Open

ActiveModel::Errors support #44

calebuharrison opened this issue Oct 4, 2024 · 1 comment
Labels
enhancement New feature or request

Comments

@calebuharrison
Copy link

calebuharrison commented Oct 4, 2024

Hello and thanks for this fantastic gem!

In my app, I've monkeypatched the provided pack_with and unpack_with methods for the ActiveRecord::Base extension to include errors by default:

class UniversalID::Extensions::ActiveRecordBasePacker
  def pack_with(packer)
    packer.write record.class.name
    packer.write packable_attributes
    error_details = record.errors.details
    packer.write error_details
  end
end

class UniversalID::Extensions::ActiveRecordBaseUnpacker
  class << self
    def unpack_with(unpacker)
      class_name = unpacker.read
      attributes = unpacker.read || {}
      instance = create_instance(class_name, attributes)
      error_details = unpacker.read

      error_details.each do |attribute, details_array|
        details_array.each do |error_details|
          error_type = error_details.delete(:error)
          instance.errors.add(attribute, error_type, **error_details)
        end
      end

      instance
    end
  end
end

This has opened up a really nice little flow in my controllers with the help of a simple utility class:

class ApplicationController < ActionController::Base
  # ...

  private

  def flash_pack
    return @flash_pack if defined?(@flash_pack)
    @flash_pack = FlashPack.new(flash)
  end

  class FlashPack
    def initialize(flash)
      @flash = flash
    end

    def []=(key, value)
      @flash[key] = URI::UID.build(value, include_changes: true).payload
    end

    def [](key)
      URI::UID.from_payload(@flash[key]).decode if @flash[key]
    end
  end
end
class PostsController < ApplicationController
  def new
    # view renders form_with model: @post, including validation errors from previous form submission (if present)
    @post = flash_pack[:post] || Post.new
  end

  def create
    post = Post.new(post_params)

    if post.save
      redirect_to another_controller_action
    else
      # pack the post into the flash
      flash_pack[:post] = post
    end
  end
end

Since the extension shipped by the gem is for ActiveRecord::Base, I think out-of-the-box support for errors would be great! I imagine this behavior could be toggled with an additional prepack option, include_errors.

Happy to write a PR if this sounds reasonable to you! Thanks again for all of your contributions to the ruby and rails ecosystems.

@hopsoft
Copy link
Owner

hopsoft commented Dec 17, 2024

This is fantastic. I'd be happy to accept a PR for this. 🙌🏻

@hopsoft hopsoft added the enhancement New feature or request label Dec 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants