Code Monkey home page Code Monkey logo

attr-gather's Introduction

about:me

My name is Ian, welcome to my :octocat: profile. My philosophy in life is that keeping a beginner's mindset, staying grateful and helping others are the keys to success. I try to do all three of those things and stumble on the way.

I'm also bad at organizing profile pages, so here's a brain dump. Enjoy!

about:facts

  • ๐Ÿ“ Live in Atlanta, GA.
  • ๐Ÿ“ฅ Currently job is Staff Production Engineer @Shopify (hey Shopifolk!).
  • ๐ŸŽน Produced electronic music as fnesse and iONik.
  • ๐ŸŽพ Tennis guru, Serena + Federer all day.
  • ๐Ÿ‡ฌ๐Ÿ‡ง 50% British, 75.2% sarcastic.
  • ๐Ÿงผ In recovery (13 clean + serene).
  • โค๏ธ Is the answer.

about:skills

  • ๐Ÿค Helping others first
  • ๐Ÿค˜ Rust
  • ๐Ÿ’Ž Ruby
  • ๐Ÿค” Kubernetes + Terraform
  • ๐Ÿงช React + Typescript
  • ๐Ÿ’ฅ Segfaulting in C

about:opensource

about:misc


twitter e-mail linkedin www eth

attr-gather's People

Contributors

dependabot[bot] avatar ianks avatar psparrow 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  avatar  avatar  avatar

Watchers

 avatar

attr-gather's Issues

Simple DSL for contract

Instead of:

      Contract = Class.new(Dry::Validation::Contract) do
        params do
          required(:order_id).filled(:int?)
          optional(:shopify_order).filled(:hash?)
        end

        rule(:shopify_order) do
          key.failure('id must match input order_id') if values[:order_id] != values[:shopify_order][:id]
        end
      end

      filter :contract, Contract.new

Make it:

     filter :contract do
        params do
          required(:order_id).filled(:int?)
          optional(:shopify_order).filled(:hash?)
        end

        rule(:shopify_order) do
          key.failure('id must match input order_id') if values[:order_id] != values[:shopify_order][:id]
        end
      end

Explicit schemas / contracts?

It would be nice for the workflow to verify the results of task / final result to ensure no bunk data sneaks through.

Imagine we have a task:

register :fetch_product do |sku:|
   { rooooom_image_url: 'https://image.com/i.png' }
end

It would be nice to know that invalid data is being provided somehow, maybe a contract:

class ProductContract < Dry::Validation::Contract
  params do
    optional(:room_image_url).filled(:string)
  end
end

But there are a few open questions in my mind:

  1. Do we abort the workflow if a task encounters bunk data?
  2. Do we filter the bunk data and move on?
  3. How do we notify the developer that bunk data is coming through?
  4. Do we even need to verify at all?

Any feedback here would be greatly appreciated.

Declare task dependencies like rake

What do you think of declaring task dependencies similar to how rake does it?

old:

task :fetch_user do |t|
  t.depends_on = [:fetch_post]
end

new:

task fetch_user: :fetch_post

Rename task to something else?

Currently, the thing that does the fetching is called a task, should this be renamed? Currently:

task :fetch_post do |t|
  t.depends_on = [:foo]
end

Other Options

  1. gather
gather :wordpress_blog_post do |t|
  t.depends_on = [:foo]
end
  1. fetch
fetch :wordpress_blog_post do |t|
  t.depends_on = [:foo]
end
  1. Can you think of a better name?

Allow for simple `inline` container

Sometimes it's nice to be able to have a method be called on the class, so something like this (with less boilerplate):

    class EnhanceMarketplaceOrder
      include Attr::Gather::Workflow

      container self

      task :fetch_shopify_order do |t|
        t.depends_on = []
      end

      def self.resolve(name)
        method(name)
      end

      def self.fetch_shopify_order(order_id:, **input)
        shopify_http = ::Shopify::HTTP.pool
        base_url = Shopify::Configuration.base_rest_api_path
        url = "#{base_url}/orders/#{order_id}"
        shopify_order = shopify_http.with { |p| p.get(url) }.parse

        { **input, shopify_order: shopify_order[:order] }
      end
    end

Container for registering task implementations, yay or nay?

Currently, task implementations are registered in a Dry::Container. The idea behind this is to seperate the workflow definition from the actual implementation code. This should allow for easier testing and make the code more readable. Also, there is an option to register alternate data providers that way.

# ./blog_post_enhancer/implementation.rb
module BlogPostEnhancer
  class Implementation
    extend Dry::Container::Mixin

    register 'fetch_post' do |id:, **_attrs|
      res = HTTP.get("https://jsonplaceholder.typicode.com/posts/#{id}")
      post = JSON.parse(res.to_s, symbolize_names: true)

      { title: post[:title], user_id: post[:userId], body: post[:body] }
    end

    register 'fetch_user' do |user_id:, **_attrs|
      res = HTTP.get("https://jsonplaceholder.typicode.com/users/#{user_id}")
      user = JSON.parse(res.to_s, symbolize_names: true)

      { user: { name: user[:name], email: user[:email] } }
    end
  end
end

With the implementation separated, we then have a very easy to read workflow file:

# ./blog_post_enhancer/workflow.rb
module BlogPostEnhancer
  class Workflow
    extend Attr::Gather::Workflow

    container Implementation

    task :fetch_post do |t|
      t.depends_on = []
    end

    task :fetch_user do |t|
      t.depends_on = [:fetch_post]
    end
  end
end

What are you thoughts on this? Could it be easier? Should be provide shortcuts? Open to any ideas here :)

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.