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`.