README.md in avromatic-1.0.0 vs README.md in avromatic-2.0.0
- old
+ new
@@ -6,10 +6,13 @@
[travis]: http://travis-ci.org/salsify/avromatic
`Avromatic` generates Ruby models from [Avro](http://avro.apache.org/) schemas
and provides utilities to encode and decode them.
+**This README reflects unreleased changes in Avromatic 2.0. Please see the
+[1-0-stable](https://github.com/salsify/avromatic/blob/1-0-stable/README.md) branch for the latest stable release.**
+
## Installation
Add this line to your application's Gemfile:
```ruby
@@ -47,10 +50,14 @@
* **eager_load_models**: An optional array of models, or strings with class
names for models, that are added to `nested_models` at the end of
`Avromatic.configure` and during code reloading in Rails applications. This
option is useful for defining models that will be extended when the load order
is important.
+* **allow_unknown_attributes**: Optionally allow model constructors to silently
+ ignore unknown attributes. Defaults to `false`. WARNING: Setting this to `true`
+ will result in incorrect union member coercions if an earlier union member is
+ satisfied by a subset of the latter union member's attributes.
#### Custom Types
See the section below on configuring [Custom Types](#custom-type-configuration).
@@ -114,32 +121,51 @@
```ruby
class MyModel
include Avromatic::Model.build(schema_name :my_model)
end
+
+# Construct instances by passing in a hash of attributes
+instance = MyModel.new(id: 123, name: 'Tesla Model 3', enabled: true)
+
+# Access attribute values with readers
+instance.name # => "Tesla Model 3"
+
+# Models are immutable by default
+instance.name = 'Tesla Model X' # => NoMethodError (private method `name=' called for #<MyModel:0x00007ff711e64e60>)
+
+# Booleans can also be accessed by '?' readers that coerce nil to false
+instance.enabled? # => true
+
+# Models implement ===, eql? and hash
+instance == MyModel.new(id: 123, name: 'Tesla Model 3', enabled: true) # => true
+instance.eql?(MyModel.new(id: 123, name: 'Tesla Model 3', enabled: true)) # => true
+instance.hash # => -1279155042741869898
+
+# Retrieve a hash of the model's attributes via to_h, to_hash or attributes
+instance .to_h # => {:id=>123, :name=>"Tesla Model 3", :enabled=>true}
```
Or an `Avro::Schema` object can be specified directly:
```ruby
class MyModel
include Avromatic::Model.build(schema: schema_object)
end
```
-Models are generated as [Virtus](https://github.com/solnic/virtus) value
+Models are generated as immutable value
objects by default, but can optionally be defined as mutable:
```ruby
class MyModel
include Avromatic::Model.build(schema_name :my_model, mutable: true)
end
```
-`Virtus` attributes are added for each field in the Avro schema
-including any default values defined in the schema. `ActiveModel` validations
-are used to define validations on certain types of fields ([see below](#validations)).
+Generated models include attributes for each field in the Avro schema
+including any default values defined in the schema.
A model may be defined with both a key and a value schema:
```ruby
class MyTopic
@@ -174,21 +200,21 @@
```
#### Experimental: Union Support
Avromatic contains experimental support for unions containing more than one
-non-null member type. This feature is experimental because Virtus attributes
+non-null member type. This feature is experimental because Avromatic
may attempt to coerce between types too aggressively.
For now, if a union contains [nested models](#nested-models) then it is
recommended that you assign model instances.
Some combination of the ordering of member types in the union and relying on
model validation may be required so that the correct member is selected,
especially when deserializing from Avro.
-In the future, the type coercion used in the gem will be replaced to better
+In the future, the type coercion used in the gem will be enhanced to better
support the union use case.
#### Nested Models
Nested models are models that are embedded within top-level models generated
@@ -249,13 +275,10 @@
Custom types can be configured for fields of named types (record, enum, fixed).
These customizations are registered on the `Avromatic` module. Once a custom type
is registered, it is used for all models with a schema that references that type.
It is recommended to register types within a block passed to `Avromatic.configure`:
-Note: custom types are not currently supported on members of unions with more
-than one non-null type.
-
```ruby
Avromatic.configure do |config|
config.register_type('com.example.my_string', MyString)
end
```
@@ -379,21 +402,36 @@
# => instance of MyModel1
decoder.decode(model2_message_value)
# => instance of MyModel2
```
-### Validations
+### Validations and Coercions
-The following validations are supported:
+An exception will be thrown if an attribute value cannot be coerced to the corresponding Avro schema field's type.
+The following coercions are supported:
-- The size of the value for a fixed type field.
-- The value for an enum type field is in the declared set of values.
-- Presence of a value for required fields. Empty arrays and maps are considered
- valid for required fields.
-- Validity of nested records, including records embedded in array, maps, and
- unions.
+| Ruby Type | Avro Type |
+| --------- | --------- |
+| String, Symbol | string |
+| Array | array |
+| Hash | map |
+| Integer, Float | int |
+| Integer | long |
+| Float | float |
+| Float | double |
+| String | bytes |
+| Date, Time, DateTime | date |
+| Time, DateTime | timestamp-millis |
+| Time, DateTime | timestamp-micros |
+| TrueClass, FalseClass | boolean |
+| NilClass | null |
+| Hash | record |
+Validation of required fields is done automatically when serializing a model to Avro. It can also be done
+explicitly by calling the `valid?` or `invalid?` methods from the
+[ActiveModel::Validations](https://edgeapi.rubyonrails.org/classes/ActiveModel/Validations.html) interface.
+
### Logical Types
Currently the official Apache Avro Ruby library does not support logical types ([AVRO-1695](https://issues.apache.org/jira/browse/AVRO-1695)).
That feature is in progress and will hopefully be merged soon.
@@ -415,15 +453,9 @@
using Avromatic with a fake schema registry during tests.
Requiring this file configures a RSpec before hook that directs any schema
registry requests to a fake, in-memory schema registry and rebuilds the
`Avromatic::Messaging` object for each example.
-
-### Unsupported/Future
-
-The following types/features are not supported for generated models:
-
-- Custom types for members within a union.
## Development
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.