README.md in alba-2.2.0 vs README.md in alba-2.3.0

- old
+ new

@@ -41,11 +41,11 @@ Alba is faster than most of the alternatives. We have a [benchmark](https://github.com/okuramasafumi/alba/tree/main/benchmark). ### Easy -Alba is easy to use because there are only a few methods to remember. It's also easy to understand due to clean and short codebase. Finally it's easy to extend since it provides some methods for override to change default behavior of Alba. +Alba is easy to use because there are only a few methods to remember. It's also easy to understand due to clean and small codebase. Finally it's easy to extend since it provides some methods for override to change default behavior of Alba. ### Feature rich While Alba's core is simple, it provides additional features when you need them, For example, Alba provides [a way to control circular associations](#circular-associations-control), [root key and association resource name inference](#root-key-and-association-resource-name-inference) and [supports layouts](#layout). @@ -141,24 +141,39 @@ ``` To check if inference is enabled etc, inspect the return value of `inflector`: ```ruby -if Alba.inflector == nil - puts "inflector not set" +if Alba.inflector.nil? + puts 'inflector not set' else puts "inflector is set to #{Alba.inflector}" end ``` +### Naming + +Alba tries to infer resource name from class name like the following. + +|Class name|Resource name| +| --- | --- | +| FooResource | Foo | +| FooSerializer | Foo | +| FooElse | FooElse | + +Resource name is used as the default name of the root key, so you might want to name it ending with "Resource" or "Serializer" + +When you use Alba with Rails, it's recommended to put your resource/serializer classes in corresponding directory such as `app/resources` or `app/serializers`. + ### Simple serialization with root key You can define attributes with (yes) `attributes` macro with attribute names. If your attribute need some calculations, you can use `attribute` with block. ```ruby class User attr_accessor :id, :name, :email, :created_at, :updated_at + def initialize(id, name, email) @id = id @name = name @email = email @created_at = Time.now @@ -354,15 +369,15 @@ attributes :id # Second proc works as a filter many :articles, - proc { |articles, params, user| - filter = params[:filter] || :odd? - articles.select {|a| a.id.send(filter) && !user.banned } - }, - resource: ArticleResource + proc { |articles, params, user| + filter = params[:filter] || :odd? + articles.select { |a| a.id.__send__(filter) && !user.banned } + }, + resource: ArticleResource end user = User.new(1) article1 = Article.new(1, 'Hello World!', 'Hello World!!!') user.articles << article1 @@ -382,12 +397,12 @@ include Alba::Resource attributes :id many :articles, - key: 'my_articles', # Set key here - resource: ArticleResource + key: 'my_articles', # Set key here + resource: ArticleResource end UserResource.new(user).serialize # => '{"id":1,"my_articles":[{"title":"Hello World!"}]}' ``` @@ -450,11 +465,11 @@ class FooResourceWithParamsOverride include Alba::Resource root_key :foo - one :bar, resource: BarResource, params: { expose_secret: false } + one :bar, resource: BarResource, params: {expose_secret: false} end Baz = Struct.new(:data, :secret) Bar = Struct.new(:baz) Foo = Struct.new(:bar) @@ -542,10 +557,52 @@ # => Same as `FooResource.new(something).serialize` when `something` is an instance of `Foo`. ``` Although this might be useful sometimes, it's generally recommended to define a class for Resource. +#### Inline definition for multiple root keys + +While Alba doesn't directly support multiple root keys, you can simulate it with `Alba.serialize`. + +```ruby +# Define foo and bar local variables here + +Alba.serialize do + attribute :key1 do + FooResource.new(foo).to_h + end + + attribute :key2 do + BarResource.new(bar).to_h + end +end +# => JSON containing "key1" and "key2" as root keys +``` + +Note that we must use `to_h`, not `serialize`, with resources. + +We can also generate a JSON with multiple root keys without making any class by the combination of `Alba.serialize` and `Alba.hashify`. + +```ruby +# Define foo and bar local variables here + +Alba.serialize do + attribute :foo do + Alba.hashify(foo) do + attributes :id, :name # For example + end + end + + attribute :bar do + Alba.hashify(bar) do + attributes :id + end + end +end +# => JSON containing "foo" and "bar" as root keys +``` + ### Serializable Hash Instead of serializing to JSON, you can also output a Hash by calling `serializable_hash` or the `to_h` alias. Note also that the `serialize` method is aliased as `to_json`. ```ruby @@ -794,24 +851,19 @@ ```ruby module CustomInflector module_function - def camelize(string) - end + def camelize(string); end - def camelize_lower(string) - end + def camelize_lower(string); end - def dasherize(string) - end + def dasherize(string); end - def underscore(string) - end + def underscore(string); end - def classify(string) - end + def classify(string); end end Alba.inflector = CustomInflector ``` @@ -924,11 +976,11 @@ @name = name @email = email end def email - raise RuntimeError, 'Error!' + raise 'Error!' end end class UserResource include Alba::Resource @@ -1120,12 +1172,14 @@ Sometimes we want to serialize a collection into a Hash, not an Array. It's possible with Alba. ```ruby class User attr_reader :id, :name + def initialize(id, name) - @id, @name = id, name + @id = id + @name = name end end class UserResource include Alba::Resource @@ -1287,12 +1341,12 @@ ```ruby module AlbaExtension # Here attrs are an Array of Symbol def formatted_time_attributes(*attrs) attrs.each do |attr| - attribute attr do |object| - time = object.send(attr) + attribute(attr) do |object| + time = object.__send__(attr) time.strftime('%m/%d/%Y') end end end end @@ -1345,16 +1399,17 @@ Alba currently doesn't support logging directly, but you can add your own logging module to Alba easily. ```ruby module Logging - def serialize(...) # `...` was added in Ruby 2.7 + # `...` was added in Ruby 2.7 + def serialize(...) puts serializable_hash super(...) end end -FooResource.prepend Logging +FooResource.prepend(Logging) FooResource.new(foo).serialize # => "{:id=>1}" is printed ``` Here, we override `serialize` method with `prepend`. In overridden method we print the result of `serializable_hash` that gives the basic hash for serialization to `serialize` method. Using `...` allows us to override without knowing method signiture of `serialize`.