These are chat archives for dry-rb/chat

24th
May 2016
Tim Riley
@timriley
May 24 2016 01:11
Well look here, a brief intro to Roda and a sneaky first mention of dry-web! https://twitter.com/timriley/status/734913916287877121
Ralf Schmitz Bongiolo
@mrbongiolo
May 24 2016 02:36
@pabloh this is something I started working on some time ago: https://gist.github.com/mrbongiolo/33370a007df3165339a5ef8ae1ad4202
It was based on Roda + Trailblazer for an API. Not sure if that's what you were looking for.
Oskar Szrajer
@gotar
May 24 2016 06:39
@timriley thx for another great article I already force all my co wokers from BKK to be at conference just for your talk ;]
Tim Riley
@timriley
May 24 2016 07:14
@gotar haha! That's awesome :)
Oskar Szrajer
@gotar
May 24 2016 07:15
I wrote them few projects in ROM+Roda, and left ;] now they need to learn fast and hard
then I think they will have a lot of questions
or at least be very focused during talk
Tim Riley
@timriley
May 24 2016 10:29
Releasing dry-container 0.3.4, which just has a small refactor I need before I can release a dry-auto_inject update
Andy Holland
@AMHOL
May 24 2016 10:43
Nice one @timriley
Piotr Solnica
@solnic
May 24 2016 11:10
I think we should rename dry-container to dry-hello-kitty so that people can stop comparing this to .net and java IoC monstrosities
Alexander Gräfe
@rickenharp
May 24 2016 11:14
dry-bucket?
Or maybe dry-vessel. :)
Tim Riley
@timriley
May 24 2016 11:26
Heh.
Luca Guidi
@jodosha
May 24 2016 11:27
dry-code
Tim Riley
@timriley
May 24 2016 11:50
It bothers me that the cost of dry-validation schema generation means that can’t really be auto-injected like all my other dependencies.
I wonder if there’s a way we could work around this...
Hannes Nevalainen
@kwando
May 24 2016 11:58
@timriley you can register it manually instead, my_container.register('my_validation_schema', Dry::Validation.Schema{ #do your stuff })
then it will use the same instance everytime
Andy Holland
@AMHOL
May 24 2016 11:59
You could also assign to a constant
Tim Riley
@timriley
May 24 2016 11:59
@kwando this is true! The next step would be to find some way to write a rule/policy for that and have it done for me.
@AMHOL But I can’t inject the constant like my other dependencies
We use the constants like that at the moment.
Nikita Shilnikov
@flash-gordon
May 24 2016 12:00
@timriley I don't know if it is helpful, but I have a custom resolver for my container that caches block result once it was resolved. Most of my classes does not have any state so I'm OK with having the only instance
Tim Riley
@timriley
May 24 2016 12:00
Foo::ArticleSchema = Dry::Validation.Schema do .. end
but I’m writing my talk for RDRC and it feels odd to have to explain (or ignore) why this particular dependency can’t be injected like the others.
@flash-gordon that’s a neat idea. Perhaps I could do something like this and have a naming rule/convention about what to cache like you describe and what to treat like normal
Andy Holland
@AMHOL
May 24 2016 12:02
@timriley not sure I'm following? You can just do container.register('articles.schema', Foo::ArticleSchema) and inject as normal can't you?
Tim Riley
@timriley
May 24 2016 12:02
@AMHOL ah yeah, I was just searching for a way to avoid manual registration :)
Andy Holland
@AMHOL
May 24 2016 12:03
Ahh OK
Tim Riley
@timriley
May 24 2016 12:03
I want to avoid too many special cases
especially when regular apps will have lots of validation schemas
Hannes Nevalainen
@kwando
May 24 2016 12:05
I implemented my own "auto registration" code
Tim Riley
@timriley
May 24 2016 12:06
I’d be interested to take a look if it’s something you can share, @kwando.
Hannes Nevalainen
@kwando
May 24 2016 12:07
I also experimented with my own DSL on top off dry-*, not sure if I like it or not yet though.
Andy Holland
@AMHOL
May 24 2016 12:07
You can pass a block to auto_register! in dry-component?
Hannes Nevalainen
@kwando
May 24 2016 12:08
@AMHOL I had som troubles with that
I think it expects a constant, infered from the path, to be defined
Andy Holland
@AMHOL
May 24 2016 12:08
Yeah, that seems to be the case
Tim Riley
@timriley
May 24 2016 12:16
Might experiment more in the morning. In the meantime, I’m just gonna hand-wave over this and keep writing the talk :)
Hannes Nevalainen
@kwando
May 24 2016 12:16
I also experimented with having a thin layer above dry-v stuff to make it easier to define stuff.
MyApp::Setup.input_schema('web.tickets.show.input'){
  required(:id).filled(:int?)
}
Tim Riley
@timriley
May 24 2016 12:16
The other thing with dry-v that would be nice is if we could work out an auto_inject strategy so you don’t have to use its #with to inject outside dependencies.
Hannes Nevalainen
@kwando
May 24 2016 12:17
not sure if it is a good idea or not yet though
Tim Riley
@timriley
May 24 2016 12:17
@kwando Interesting. So I suppose that would register the object with the container, yes?
Hannes Nevalainen
@kwando
May 24 2016 12:23

yeah, it is implemented something like this.

module MyApp
  class SchemaAdapter
    def initialize(schema)
      @schema = schema
    end

    def call(input)
      result = @schema.call(input)
      if result.success?
        Right(result.output)
      else
        Left([:input_validation_error, result.messages])
      end
    end
  end

  module Setup
    def self.input_schema(name, &block)
      Container.register(name, SchemaAdapter.new(Dry::Validation.Form(&block)))
    end
  end
end

got similar stuff for setting up dry-transactions

one awesome aspect of "functional objects" is that it is really easy to add wrappers/decorators =)
Tim Riley
@timriley
May 24 2016 12:30
Yes, true!
Piotr Solnica
@solnic
May 24 2016 12:36
@kwando we’re planning pretty cool monitoring/instrumentation APIs thanks to this fact
Hannes Nevalainen
@kwando
May 24 2016 12:37
@solnic that would be awesome =)
Piotr Solnica
@solnic
May 24 2016 12:37
it should be trivial to attach monitoring to every component in your app
I’ve been talking to @AMHOL about dry-monitor APIs ideas already
feel free to chime in
Piotr Solnica
@solnic
May 24 2016 12:52
http://rwdtow.stdout.in ok so this is pretty awesome
Andy Holland
@AMHOL
May 24 2016 13:02
That is awesome :D
Piotr Solnica
@solnic
May 24 2016 13:16
would be cool to help with this, it’s quite comprehensive
Adam Davies
@adz
May 24 2016 13:19
:+1: just read it too
Ralf Schmitz Bongiolo
@mrbongiolo
May 24 2016 13:48
@kwando thanks for the examples, I might need something similar for my dry-rb based operation. Still not yet fully satisfied with what's going
Piotr Solnica
@solnic
May 24 2016 13:49
@mrbongiolo better report an issue and described what you want to achieve
Ralf Schmitz Bongiolo
@mrbongiolo
May 24 2016 13:56
@solnic was you talking about my last comment? I just wasn't yet satisfied in how my stack on top of dry-rb is doing :D
Piotr Solnica
@solnic
May 24 2016 13:56
yes, so please explain why and we can figure out how to make it better
Ralf Schmitz Bongiolo
@mrbongiolo
May 24 2016 14:20

Right now I'm using dry-transactions and dry-containers to create an "operation" or "handler" class like this:

class WithFacebook < Miss::Operation

          register :schema, Dry::Validation.Schema {
            required(:provider).filled(:str?, format?: 'facebook')
            required(:facebook_id).filled(:str?)
            required(:device_id).maybe(:str?)
          }

          register :find_model, -> input {
            model = ::Customer.find_by!(facebook_id: input[:facebook_id])
            [model, input]
          }

          register :update_model, -> args {
            model, input = args
            model.update(
              device_id: input[:device_id],
              api_token: Miss::TokenFactory.call(type: :customer_api_token)
            )
          }

          register :decorate, -> args {
            Decorators::Resource::WithApiToken.new(args[0])
          }

          perform do
            validate :schema
            try :find_model,
              catch: ActiveRecord::RecordNotFound,
              raise: Miss::EntityNotFound
            tee :update_model
            map :decorate
          end
        end

and then I can call it from my controllers like this:

def authenticate
    Api::V1::Customer::Authenticate.call(params) do |m|
      m.success { |input| return handle_success(input) }
      m.failure { |error| return handle_failure(error) }
    end
  end
Since I'm in a rails env I'm not so sure about using an app wide container, right now my operation itself creates it own container to be used by the perform,
A container can "inherit" from another container? or atleast use it as base?
Ralf Schmitz Bongiolo
@mrbongiolo
May 24 2016 14:25
Or maybe I just need an easier way to register my dependencies into namespaces, so I could call some of them like:
perform do
  validate :schema
  try :find_model, with: 'customer.find_by.facebook_id' #crazy idea here, might not be useful
  tee :update_model
  map :decoreate, with 'api.v1.customer.authenticate.decorators.resource.with_api_token'
end
Piotr Solnica
@solnic
May 24 2016 14:29
one per-app container is all you need
it also becomes a nice single-entry point to access your application core APIs
you are gonna love opening up console and using your app with its API
Ralf Schmitz Bongiolo
@mrbongiolo
May 24 2016 14:30
and how should I register nested namespaced dependencies?
Piotr Solnica
@solnic
May 24 2016 14:30
just like you showed
”foo.bar.baz”
Ralf Schmitz Bongiolo
@mrbongiolo
May 24 2016 14:31
but when should I register them? LIke, just write my code block and call AppContainer.register('foo.bar.baz', something)?
Piotr Solnica
@solnic
May 24 2016 14:33
yes, I used an initializer in rails for that
and split it up into sep files for nice organization
worked very well
Ralf Schmitz Bongiolo
@mrbongiolo
May 24 2016 14:33
Some of the dependencies from this Operation should go outside, but I would like to keep the Schema in there, since it's easier to read it later on, and not try to find another file with just the Schema
Piotr Solnica
@solnic
May 24 2016 14:34
I use constants for schemas
Ralf Schmitz Bongiolo
@mrbongiolo
May 24 2016 14:34
I see
but even so I would need to register something to call that constant so that the transaction step could use it
I guess I know what I could do, when I'm inside and operation I can override the register method so that it already add those dependencies inside a namespace, and when calling perform I could check if the step is not using with I will just prepend the current namespace to the step name. So with: 'something.thats.not.in.this.current.namespace' can be used to access dependencies that are somewhere else...
Ralf Schmitz Bongiolo
@mrbongiolo
May 24 2016 14:41
Another quest @solnic, it's better to keep those dependencies outside of Rails app folder right? Or autoloadingdoesn't interfere?
Piotr Solnica
@solnic
May 24 2016 14:43
sorry man I’m busy atm
I’ll get back to you
Ralf Schmitz Bongiolo
@mrbongiolo
May 24 2016 14:43
No problem.
Joe Van Dyk
@joevandyk
May 24 2016 22:15
totally off topic… has anyone dealt with utf8 much? i’m running into problems with people submitting doubly-encoded utf8 data. for example "you’re” instead of “you’re”. or sometimes providing utf-8 noncharacters. it’s valid utf8, but i want to reject it.
when we forward that data to google, they correctly tell us https://monosnap.com/file/9hq45848KhCUHaUpS6qdtI0vR1oWsV.png
googling is doing shit for me. ;(
Tim Riley
@timriley
May 24 2016 23:29
I started some work on dry-rb/dry-auto_inject#16, but it got a tad complex now that we theoretically support multiple include AutoInject.kwarg[…] includes in the same class
Tim Riley
@timriley
May 24 2016 23:39
I have a sneaking feeling that it might only be feasible for injections for regular positional args
Actually, this is only true if we take a simplistic approach. The proper approach will need a bit more time :)
Piotr Solnica
@solnic
May 24 2016 23:48
Wait. Why multiple includes? You mean in an inheritance hierarchy?
Tim Riley
@timriley
May 24 2016 23:49
dry-rb/dry-auto_inject#13
I’m not sure of the particular use case @flash-gordon had in mind, but putting the .new definition into a module seemed an improvement regardless. I usually end up needed to do things like that anyway for dynamically defined methods.
Anyway, yes. This is effectively inheritance.
I think for #16 to work with kwargs we just need to do some more introspection of the super method’s parameters to work out which args to pass up to it.