DEV: Introduce an array type for Chat contracts (#22278)

This small patch registers a new `ActiveModel` type: `array`.
It will split a string on `,` to create a new array. If the value is
already an array, nothing will happen and for all other types, it will
wrap the value in an array.

Here’s an example on an existing contract:
```ruby
  attribute :target_usernames

  before_validation do
    self.target_usernames =
      (
        if target_usernames.is_a?(String)
          target_usernames.split(",")
        else
          target_usernames
        end
      )
  end

  # can be rewritten as:

  attribute :target_usernames, :array
```
This commit is contained in:
Loïc Guitaut 2023-06-27 02:51:58 +02:00 committed by GitHub
parent 6517e6d47a
commit 885ab9a015
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 57 additions and 0 deletions

View File

@ -0,0 +1,20 @@
# frozen_string_literal: true
module Chat
module Types
class Array < ActiveModel::Type::Value
def serializable?(_)
false
end
def cast_value(value)
case value
when String
value.split(",")
else
::Array.wrap(value)
end
end
end
end
end

View File

@ -496,6 +496,8 @@ after_initialize do
)
register_bookmarkable(Chat::MessageBookmarkable)
ActiveModel::Type.register(:array, Chat::Types::Array)
end
if Rails.env == "test"

View File

@ -0,0 +1,35 @@
# frozen_string_literal: true
require "rails_helper"
RSpec.describe Chat::Types::Array do
subject(:type) { described_class.new }
describe "#cast" do
subject(:casted_value) { type.cast(value) }
context "when 'value' is a string" do
let(:value) { "first,second,third" }
it "splits it" do
expect(casted_value).to eq(%w[first second third])
end
end
context "when 'value' is an array" do
let(:value) { %w[existing array] }
it "returns it" do
expect(casted_value).to eq(value)
end
end
context "when 'value' is something else" do
let(:value) { Time.current }
it "wraps it in a new array" do
expect(casted_value).to eq([value])
end
end
end
end