JenniferTwin
Super simple library to dump/load Jennifer model attributes to plain class instance to be able to integrate it with any kind of hidden attributes.
Installation
- Add the dependency to your
shard.yml
:
dependencies:
jennifer_twin:
github: imdrasil/jennifer_twin
version: 0.1.1
- Run
shards install
Usage
Jennifer generates some amount of hidden attributes for a mode to be able to track whether attribute has been changed, relation load state or just a collection, etc. For some tasks you would like to have an instance containing only model attributes or it's subset. One of the most popular example - JSON::Serializable
. Therefor JenniferTwin copies all data from original instance and store them.
If you trying to solve issue of model serialization to JSON - take a look at Serializer.
To create a twin include JenniferTwin
and call .map_fields
macro:
require "jennifer_twin"
class UserTwin
include JenniferTwin
map_fields User
end
Mapping
.map_fields
macro generates only 3 things:
- getters for all fields named after model's ones (unless other name is specified)
- initializer accepting model instance to copy
#to_model
method to create a model instance from it's fields
user = User.all.first
user_twin = UserTwin.new(user)
user_twin.to_model # => User
As a 2nd argument macro accepts named tuple or symbol-based hash of field options. Supported options are:
:ignore
- if set totrue
ignores specified field:key
- defines attribute with the specified value:annotations
- adds annotations above field setter
Let's take a look at more descriptive example:
class User < Jennifer::Model::Base
mapping(
id: Primary32,
name: String?,
age: Int32?,
password_hash: String?
)
end
class UserTwin
include JenniferTwin
include JSON::Serializable
map_fields(User, {
age: { annotations: [@[JSON::Field(emit_null: true)]] }
name: { key: :full_name },
password_hash: { ignore: true }
})
setter full_name
end
user = User.all.first # <User:0x000000000010 id: 1, name: "User 8", age: nil, password_hash: "<hash>">
user_twin = UserTwin.new(user) # <UserTwin:0x000000000020 @id=1, @full_name="User 8", @age=nil>
user_twin.to_json # => %({"id":1,"full_name":"User 8","age":null})
user_twin.full_name = "New Name"
user_twin.to_modal # <User:0x000000000030 id: nil, name: "New Name", age: nil, password_hash: nil>
Also you can add additional custom logic to generated initializer passing a block to the macro call. To access model instance use record
variable name.
class UserTwin
include JenniferTwin
getter full_name : String
map_fields(User) do
@full_name = "#{record.name} Snow"
end
end
Contributing
- Fork it (<https://github.com/imdrasil/jennifer_twin/fork>)
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create a new Pull Request
Contributors
- Roman Kalnytskyi - creator and maintainer