Simple DSL designed with View Components in mind to make defining and setting keyword arguments and instance variables easier.
Before:
class HeadingComponent < ApplicationComponent
def initialize(text:, tag: "h1", **options)
@text = text
@tag = tag
@options = options
end
end
After:
class HeadingComponent < ApplicationComponent
include VCDry::DSL
keyword :text
keyword :tag, default: "h1"
other_keywords :options
end
Add this line to your application's Gemfile:
gem "vcdry"
And then execute:
bundle install
Include VCDry::DSL
in your component.
class ApplicationComponent < ViewComponent::Base
include VCDry::DSL
end
Use the keyword
method to define a keyword.
class MyComponent < ApplicationComponent
keyword :name
end
By default, specifying an unknown keyword results in an error.
MyComponent.new(class: "mt-1")
# unknown keyword: :class (VCDry::UnknownArgumentError)
To disable this behavior, specify strick_keywords false
.
class MyComponent < ApplicationComponent
strict_keywords false
end
Or, to save those unknown keywords into a variable, use other_keywords
.
class MyComponent < ApplicationComponent
other_keywords :options
end
Keywords specified on a parent component are inherited by a child component.
class ApplicationComponent < ViewComponent::Base
include VCDry::DSL
other_keywords :options
end
class ParentComponent < ApplicationComponent
keyword :name
end
class ChildComponent < ParentComponent
keyword :age
end
ChildComponent.new(name: "Child", age: 7, class: "mt-1").instance_variables
# => [:@name, :@age, :@options]
Define a keyword variable to read and store to an instance variable when instantiating a component.
class MyComponent
keyword :name
end
Specify a type to typecast the value specified.
class MyComponent
keyword :name, :string
end
You can use any of the built-in types or create your own as defined in Types. Additionally you can specify a proc to define your own one off type for a component.
class MyComponent
keyword :name, ->(value) { "custom #{value}" }
end
By default, keywords are required. To make a keyword optional, specify a default
value using the :default
or pass optional: true
.
class MyComponent
keyword :padding, :integer, optional: true
keyword :size, :symbol, default: :md
end
When specifying a default, you can also pass the value as a proc to resolve the default value.
class MyComponent
keyword :options, :hash, default: -> { Hash.new }
end
You can instruct a keyword to only accept a predefined set of values by using
the :values
option.
class MyComponent
keyword :size, :symbol, values: [:sm, :md, :lg]
end
You can also instruct a keyword to accept an array of values by passing the
array: true
option.
class MyComponent
keyword :author_ids, :string, array: true
end
A child component can override the declaration of a keyword from a parent component.
class MyOtherComponent < MyComponent
keyword :author_ids, :integer, array: true
end
To gather all keywords not explicitly defined by the keyword
method, use the
other_keywords
method.
class MyComponent
keyword :name
other_keywords :options
end
In the example above, the :name
keyword would be stored in the variable
@name
while all other keywords specified would be stored in the variable
@options
.
If you have a custom type defined that acts similarly to a Hash
(like the
TagOptions::Hash gem), you can pass
that in to the other_keywords
declaration.
class MyComponent
other_keywords :options, :tag_options
end
Note: You must register a custom type using VCDry::Types.add_type
as
detailed in Types.
By default, if you specify a unknown keyword when instantiating a component an
error will be raised. To silently discard the additional keywords, use the
strict_keywords false
declaration.
class MyComponent
keyword :name
strict_keywords false
end
To turn it back on for a component that inherits from parent component that
turned off strict keywords, use the strict_keywords true
declaration.
class MyOtherComponent < MyComponent
strict_keywords true
end
To remove a keyword specified on a component that inherits from parent
component, use the remove_keyword
method.
class MyOtherComponent < MyComponent
remove_keyword :name
end
Including VCDry::DSL
adds support through ActiveModel::Callbacks
for the
before_initialize
, after_initialization
, and around_initialize
callbacks
to minimize the need to override the initlialize method.
class MyComponent < MyComponent
before_initialize ->() { @links = [] }
after_intialize :some_method
private
def some_method
# do something fancy
end
end
The following types are built-in to vcdry
.
- boolean
- datetime
- hash
- integer
- string
- symbol
Additionally you can define custom, or override built-in, types by using
VCDry::Types.add_type
.
# config/initializers/vcdry_types.rb
VCDry::Types.add_type(:boolean, ->(value) { ActiveRecord::Type::Boolean.new.cast(value) })
VCDry::Types.add_type(:custom_hash, ->(value) { CustomHash.new(value) })
To mix-in the keyword
behavior without using the VCDry::DSL
(and its
initialize method), you can call include VCDry::Core
instead and then call
vcdry_parse_keywords
against the hash you wish to parse out keywords from.
The vcdry_parse_keywords
accepts a hash and returns a hash of all key/value
pairs that were not pulled out as a keyword
.
Note: Including
VCDry::Core
does not include support forother_keywords
,strict_keywords
, or enable support for callbacks.
class HeadingComponent
include VCDry::Core
keyword :size, :symbol, default: :md
other_keywords :options
def initialize(text, **options)
@text = text
@options = vcdry_parse_keywords(options)
end
end
After checking out the repo, run bin/setup
to install dependencies. Then, run
bin/rspec
to run the tests. You can also run:
bin/console
for an interactive prompt that will allow you to experimentbin/rubocop
to run RuboCop to check the code style and formatting
To build this gem on your local machine, run bundle exec rake build
. To
release a new version, update the version number in version.rb
, and then run
bundle exec rake release
, which will create a git tag for the version, push
git commits and the created tag, and push the .gem
file to
rubygems.org.
Bug reports and pull requests are welcome on GitHub at https://github.com/wamonroe/vcdry.
The gem is available as open source under the terms of the MIT License.