Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion lib/literal/properties.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ def self.extended(base)
base.include(base.__send__(:__literal_extension__))
end

def prop(name, type, kind = :keyword, reader: false, writer: false, predicate: false, default: nil, &coercion)
def prop(name, type, kind = :keyword, reader: false, writer: false, predicate: false, default: nil, **kwargs, &coercion)
if default && !(Proc === default || default.frozen?)
raise Literal::ArgumentError.new("The default must be a frozen object or a Proc.")
end
Expand Down Expand Up @@ -48,6 +48,7 @@ def prop(name, type, kind = :keyword, reader: false, writer: false, predicate: f
writer:,
predicate:,
default:,
**kwargs,
coercion:,
)

Expand Down
86 changes: 86 additions & 0 deletions test/properties/custom_property_class.test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# frozen_string_literal: true

class DescriptionProperty < Literal::Property
def initialize(description: nil, **kwargs)
super(**kwargs)

@description = description
end

attr_reader :description
end

module DescriptionProperties
def prop(name, type, kind = :keyword, description: nil, **, &coercion)
super
end

def __literal_property_class__
DescriptionProperty
end
end

Example = Literal::Object

test "custom property class can accept additional keyword arguments" do
example = Class.new(Example) do
extend DescriptionProperties

prop :name, String, description: "The person's name"
prop :age, Integer, description: "The person's age"
end

name_prop = example.literal_properties[:name]
age_prop = example.literal_properties[:age]

assert_equal name_prop.description, "The person's name"
assert_equal age_prop.description, "The person's age"
assert_equal name_prop.class, DescriptionProperty
assert_equal age_prop.class, DescriptionProperty
end

test "custom property class works with all property features" do
example = Class.new(Example) do
extend DescriptionProperties

prop :name, String, description: "Name", reader: :public
prop :age, Integer, description: "Age", default: 0, reader: :public
end

object = example.new(name: "John")
assert_equal object.name, "John"
assert_equal object.age, 0

name_prop = example.literal_properties[:name]
age_prop = example.literal_properties[:age]

assert_equal name_prop.description, "Name"
assert_equal age_prop.description, "Age"
end

test "custom property class with nil description" do
example = Class.new(Example) do
extend DescriptionProperties

prop :name, String
end

name_prop = example.literal_properties[:name]
assert_equal name_prop.description, nil
end

test "invalid keyword arguments on base Literal::Properties raise ArgumentError" do
example = Class.new(Example)

assert_raises(ArgumentError) do
example.prop :name, String, description: "This should fail"
end
end

test "invalid keyword arguments on base Literal::Properties raise ArgumentError for other unknown args" do
example = Class.new(Example)

assert_raises(ArgumentError) do
example.prop :name, String, unknown_arg: "This should fail"
end
end