README.md in alba-1.1.0 vs README.md in alba-1.2.0

- old
+ new

@@ -57,22 +57,18 @@ You can find the documentation on [RubyDoc](https://rubydoc.info/github/okuramasafumi/alba). ## Features -* Resource-based serialization -* Arbitrary attribute definition -* One and many association with the ability to define them inline -* Adding condition and filter to association -* Parameters can be injected and used in attributes and associations * Conditional attributes and associations * Selectable backend * Key transformation * Root key inference * Error handling * Resource name inflection based on association name * Circular associations control +* Types for validation and conversion * No runtime dependencies ## Anti features * Sorting keys @@ -246,11 +242,11 @@ RestrictedFooResouce.new(foo).serialize # => '{"name":"my foo"}' end ``` -### Attribute key transformation +### Key transformation ** Note: You need to install `active_support` gem to use `transform_keys` DSL. With `active_support` installed, you can transform attribute keys. @@ -276,10 +272,43 @@ user = User.new(1, 'Masafumi', 'Okura') UserResourceCamel.new(user).serialize # => '{"id":1,"firstName":"Masafumi","lastName":"Okura"}' ``` +You can also transform root key when: + +* `Alba.enable_inference!` is called +* `key!` is called in Resource class +* `root` option of `transform_keys` is set to true or `Alba.enable_root_key_transformation!` is called. + +```ruby +Alba.enable_inference! + +class BankAccount + attr_reader :account_number + + def initialize(account_number) + @account_number = account_number + end +end + +class BankAccountResource + include Alba::Resource + + key! + + attributes :account_number + transform_keys :dash, root: true +end + +bank_account = BankAccount.new(123_456_789) +BankAccountResource.new(bank_account).serialize +# => '{"bank-account":{"account-number":123456789}}' +``` + +This behavior to transform root key will become default at version 2. + Supported transformation types are :camel, :lower_camel and :dash. ### Filtering attributes You can filter attributes by overriding `Alba::Resource#converter` method, but it's a bit tricky. @@ -454,9 +483,48 @@ ### Circular associations control You can control circular associations with `within` option. `within` option is a nested Hash such as `{book: {authors: books}}`. In this example, Alba serializes a book's authors' books. This means you can reference `BookResource` from `AuthorResource` and vice versa. This is really powerful when you have a complex data structure and serialize certain parts of it. For more details, please refer to [test code](https://github.com/okuramasafumi/alba/blob/master/test/usecases/circular_association_test.rb) + +### Types + +You can validate and convert input with types. + +```ruby +class User + attr_reader :id, :name, :age, :bio, :admin, :created_at + + def initialize(id, name, age, bio = '', admin = false) # rubocop:disable Style/OptionalBooleanParameter + @id = id + @name = name + @age = age + @admin = admin + @bio = bio + @created_at = Time.new(2020, 10, 10) + end +end + +class UserResource + include Alba::Resource + + attributes :name, id: [String, true], age: [Integer, true], bio: String, admin: [:Boolean, true], created_at: [String, ->(object) { object.strftime('%F') }] +end + +user = User.new(1, 'Masafumi OKURA', '32', 'Ruby dev') +UserResource.new(user).serialize +# => '{"name":"Masafumi OKURA","id":"1","age":32,"bio":"Ruby dev","admin":false,"created_at":"2020-10-10"}' +``` + +Notice that `id` and `created_at` are converted to String and `age` is converted to Integer. + +If type is not correct and auto conversion is disabled (default), `TypeError` occurs. + +```ruby +user = User.new(1, 'Masafumi OKURA', '32', nil) # bio is nil and auto conversion is disabled for bio +UserResource.new(user).serialize +# => TypeError, 'Attribute bio is expected to be String but actually nil.' +``` ### Caching Currently, Alba doesn't support caching, primarily due to the behavior of `ActiveRecord::Relation`'s cache. See [the issue](https://github.com/rails/rails/issues/41784).