Giter Club home page Giter Club logo

decoratex's Introduction

Decoratex

Travis Hex.pm

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

Requirements

  • Ecto 2.0 or higher

What does this package do?

Maybe you have been in some situations where you need some related data of a model that is not straight stored with it's attributes and it requires a complex logic to calculate their value that can't be 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 model struct with these new fields.

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

Installation

The package can be installed as simply as adding decoratex to your list of dependencies in mix.exs:

  def deps do
    [{:decoratex, "~> 1.1.0"}]
  end

Usage

  1. Add use Decoratex.Schema 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 decorations() inside schema definition.
  5. Use Decoratex.decorate function with your model.
defmodule Post do
  use Ecto.Schema
  use Decoratex.Schema

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

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

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

    timestamps()
    decorations()
  end
end

The decorations definition needs to be placed before schema definition, and then, you should add decorations() inside the schema block. This will automatically add the virtual fields to your model.

Finally, you can use the decorate function of your model module to populate the fields that you need with the function associated to them.

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

# Decorate all fields
|> Decoratex.decorate

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

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

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

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

post.happy_comments_count
234

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

|> Decoratex.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: "*"
|> Decoratex.decorate(censured_comments: [pattern: list_of_words, replace: "*"])

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

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

decoratex's People

Contributors

odarriba avatar rsierra avatar techgaun avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

decoratex's Issues

Unmaintained?

Hello,

Is this repo unmaintained? It doesn't seem to work Ecto 3.x.

Cheers

Question, best way to decorate with preloaded relations

Hi all, thank you for the hard work. I have a question.

Suppose that I have a decorated field in the Post schema, but then I do something like

def preload(users_query, preloads) do
   Users
   |> Repo.all()
   |> Repo.preload(preloads)
end

where preloads is dynamic, and could be i.e. [:posts, :comments, :likes, ...]

Which is the correct way to work in cases where you preload the relations, and those relations have decorated fields?

Thank you!

Refactor decorate methods

All decorate methods are added in the quote block of the main defmacro, so you can use it straight as a method of the schema module:

MyModule.decorate(my_module)

But the defmacro is to big and i'm not sure if include this methods to the schema module is a good choice.

Maybe the right way in a new mayor version is to add a new module inside the lib, and use it for an explicit decoration:

Decoratex.apply(my_module)

undefined function __decorations__/0

if I add "use Decoratex" to web.ex, those models doesn't have define function "decorators" raise "CompileError, undefined function decorations/0"

Document and test usage on embedded schemas

Decoratex only reads data from existing fields in the struct model, and creates some virtual fields to store the calculated data.

Since fetching the required data for performing the calculations is external to Decorates, and must be done before running any decoration function, I think that it should also work with embedded schemas.

We could add some tests and update the documentation and examples to reflect this.

Project lacks changelog

This project lacks a changelog. This would be a helpful addition for tracking changes, especially breaking changes like those in v1.1.0.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.