Decoratex v1.0.1 Decoratex

Decoratex provides an easy way to add calculated data to your Ecto model structs.

You have to configure the name and type of these attributes and the function to calculate and load data when you need to decorate your model.

The function for each field will receibe just the current model instance as param.

What does this package do?

Maybe you were in some situations where you need some related data of a model that is not straight stored with it’s attributes and it requires complex logic to calculate their value, which can’t be easly solved with a query. Maybe you will need this data in multiple points of the instace life cicle and you want the data available in a standard way instead of using an external module function each time you need it’s value.

In this cases, this is what decoratex can do for you:

  • Add virtual fields to the model schema to let you use your model like the same struct type with these new fields.

  • Provide a function to load data in all or some of these fields whenever you want.

Usage

  1. Add use Decoratex to your models.
  2. Set the decorate fields inside a block of decorations function.
  3. Declare each field with decorate_field name, type, function, options.

    • Name of the virtual field.
    • Type of the virtual field.
    • Function to calculate the value of the virtual field. Always receives a struct model as first param.
    • Default options for the function (arity 2) in case you need to use diferent options in each decoration.
  4. Add add_decorations inside schema definition.
  5. Use decorate function of your model module.

Usage examples

Imagine that you have a blog application (with posts and comments) and you need on each post the count of comments with positive and negative content that is decided by an external natural lenguage analisys service on the fly.

defmodule Post do
  use Ecto.Schema
  use Decoratex

  decorations do
    decorate_field :happy_comments_count, :integer, &PostHelper.count_happy_comments/1
    decorate_field :troll_comments_count, :integer, &PostHelper.count_troll_comments/1
    ...
  end

  schema "posts" do
    has_many :comments, Comment, on_delete: :delete_all

    field :title, :string
    field :body, :string

    add_decorations
  end
end

Then, you can load your post with the needed data:

post = Post
|> Repo.get(1)
|> Repo.preload(:comments))

Decorate it as you need:

# Decorate all fields
|> Post.decorate

# Decorate one field with an atom
|> Post.decorate(:happy_comments_count)

# Decorate some fields with a list
|> Post.decorate([:happy_comments_count, ...])

# Decorate all fields except one with except key and an atom
|> Post.decorate(except: :happy_comments_count)

# Decorate all fields except some with except key and a list
|> Post.decorate(except: [:happy_comments_count, ...])

And use ´post.happy_comments_count´ wherever you want as regular post attribute in another methods, pattern matching, decoding as JSON…

NOTE: the fields decoration needs to be defined before de schema

Decorate with options

When you need to send some options to the decoration functions, you can define a function with arity 2, and set a default value in declaration. The default options value is mandatory for default decorations:

```
decorate_field :mention_comments_count, :integer, &PostHelper.count_mention_comments/2, ""
```

Then, you can pass the options value when the struct is decorated

```
|> Post.decorate(count_mention_comments: user.nickname)
```

You can use a keyword list for a complex logic, but you need to care about how to manage options in the decoration function (always with arity/2), and the default options in the configurtion.

```
decorate_field :censured_comments, {:array, Comment}, &PostHelper.censured_comments/2, pattern: "frack", replace: "*"
```

```
|> Post.decorate(censured_comments: [pattern: list_of_words, replace: "*"])
```

And you can mix simple and decorations with options with a list:

```
|> Post.decorate([:happy_comments_count, censured_comments: [pattern: list_of_words, replace: "*"]])
```

Summary

Macros

add_decorations()
decorate_field(name, type, function, options \\ nil)
decorations(list)