These are chat archives for dry-rb/chat

13th
May 2016
Joe Van Dyk
@joevandyk
May 13 2016 00:10
i think i would like to be able to do SomeClass.new(“dep1” => dep1)
that possible?
Tim Riley
@timriley
May 13 2016 00:15
@joevandyk in that case, you can pass nil, dep2
Joe Van Dyk
@joevandyk
May 13 2016 00:16
meh ok
Tim Riley
@timriley
May 13 2016 00:16
@joevandyk but auto_inject also supports hash and kwargs initializers
Joe Van Dyk
@joevandyk
May 13 2016 00:16
yes, i can’t figure out how to use that yet
Tim Riley
@timriley
May 13 2016 00:16
Inject.hash["dep1"] etc
or .kwargs
Might need to use master for those
Joe Van Dyk
@joevandyk
May 13 2016 00:17
so if I’m testing a Command object, I’d do in the test Command.kwargs(logger: fake_logger)?
Tim Riley
@timriley
May 13 2016 00:19
No
Command.new(logger: hi)
Joe Van Dyk
@joevandyk
May 13 2016 00:19
ah, in the Command class, i have to do include AutoInject.kwargs
Tim Riley
@timriley
May 13 2016 00:20
Yep!
Joe Van Dyk
@joevandyk
May 13 2016 00:20
seems odd to have to do that there
Tim Riley
@timriley
May 13 2016 00:20
Well, it's the place where you know what kind of initializer you want, right?
Joe Van Dyk
@joevandyk
May 13 2016 00:20
i suppose
Tim Riley
@timriley
May 13 2016 00:20
If you want to make it global, do MyInject = AutoInject(container).kwargs
And then include MyInject["foo"]
Joe Van Dyk
@joevandyk
May 13 2016 00:21
ooh cool
would be nice to add that to the docs
Tim Riley
@timriley
May 13 2016 00:22
Yep, need to do that!
Joe Van Dyk
@joevandyk
May 13 2016 00:23
can i auto inject something like ‘some.nested.thing’ somehow?
Tim Riley
@timriley
May 13 2016 00:24
Yes, that works, provided there's a matching registration!
Joe Van Dyk
@joevandyk
May 13 2016 00:24
how do i call it?
Tim Riley
@timriley
May 13 2016 00:24
thing
But in master you can do this:
Inject[my_thing: "some.thing"]
And refer to it by my_thing
Joe Van Dyk
@joevandyk
May 13 2016 00:25
oooooooo pretty. clojure has something similar i think
Tim Riley
@timriley
May 13 2016 00:26
:)
Joe Van Dyk
@joevandyk
May 13 2016 00:34
@timriley I have AutoInject.kwargs[“repos.products”] in Command. I have Command.new(“repos.products”: spy). Doesn’t seem to get set correctly.
it does work to do AutoInject.kwargs[products: “repos.products”] and then Command.new(products: spy)
ah, on the first one I have to do Command.new(products: spy)
Joe Van Dyk
@joevandyk
May 13 2016 00:48
i was a little surprised that if i pass in the dependency, it didn’t verify that the thing i passed in was a valid key in the registry
means i could accidently remove or spell something different in the registry/container and if i was passing in all my dependencies in the tests, i wouldn’t know
Joe Van Dyk
@joevandyk
May 13 2016 01:25
is activesupport’s try going to mess with dry-transaction’s try?
Tim Riley
@timriley
May 13 2016 01:27
@joevandyk if it does, let me know and I'll fix it :)
Joe Van Dyk
@joevandyk
May 13 2016 01:27
i got try :find_product, with: "commands.find_product", catch: ActiveRecord::RecordNotFound
/usr/local/tanga/ruby-2.2.4/lib/ruby/gems/2.2.0/gems/dry-transaction-0.6.0/lib/dry/transaction/dsl.rb:21:in `respond_to_missing?': wrong number of arguments (2 for 1) (ArgumentError)
    from /usr/local/tanga/ruby-2.2.4/lib/ruby/gems/2.2.0/gems/activesupport-4.2.5.2/lib/active_support/core_ext/object/try.rb:63:in `respond_to?'
    from /usr/local/tanga/ruby-2.2.4/lib/ruby/gems/2.2.0/gems/activesupport-4.2.5.2/lib/active_support/core_ext/object/try.rb:63:in `try
Tim Riley
@timriley
May 13 2016 01:29
@joevandyk that's helpful to see. What version of Ruby are you on?
Joe Van Dyk
@joevandyk
May 13 2016 01:29
2.2.4
Tim Riley
@timriley
May 13 2016 01:29
Would you mind filing an issue?
Joe Van Dyk
@joevandyk
May 13 2016 01:29
sure
any more info needed?
Tim Riley
@timriley
May 13 2016 01:30
I can take a look tomorrow :)
Joe Van Dyk
@joevandyk
May 13 2016 01:30
i can try coming up with a small test case
Tim Riley
@timriley
May 13 2016 01:30
The fact that activesupport's try is getting involved here is probably enough...
I might need to make the DSL context inherit from BasicObject or something
Joe Van Dyk
@joevandyk
May 13 2016 01:31
require 'active_support'
require 'active_support/core_ext'

Dry::Transaction(container: {foo: 1}) do
  try(:foo)
end
i’ll file issue
Phil Schalm
@pnomolos
May 13 2016 01:33
ActiveSupport - “Do or do not, you’re not allowed to ‘try’"
worked for me
This message was deleted
hm, maybe it didn’t work on master
k, fixed, had to do ::Hash for some reason
Tim Riley
@timriley
May 13 2016 01:58
Thanks!
Joe Van Dyk
@joevandyk
May 13 2016 02:41
@timriley curious about best way to test that, if it needs tests
Btw did you find anything better than boxen
We are at that point where we need something to keep the Dev machines in sync. We do all work on VM with ansible/chef, but would be nice to have something keep OS X in sync
Tim Riley
@timriley
May 13 2016 02:45
@joevandyk yep, check out icelab/babushka-deps on GitHub (and timriley/babushka-deps for my own changes on top of it)
Piotr Solnica
@solnic
May 13 2016 07:58
@joevandyk re testing and mocking/stubbing, we're still experimenting with an API for that, ie there's been some work happening to enable a mocking API for dry-container that is only available in tests. Check out dry-rb/dry-container#11 for more info
IIRC it is already available in latest release
now, when it comes to unit tests, you can simply use hash-based or kvargs-based constructors and do MyThing.new(some_dep: blah)
personally I'd recommend using container's stubbing API only for integration tests when you just want to stub some service
and in unit tests just inject mocks through constructor injection provided by auto-inject constructors
Fran Worley
@fran-worley
May 13 2016 08:03
@solnic can I push a WIP commit to a branch with failing specs or would you rather I fixed them first?
Piotr Solnica
@solnic
May 13 2016 08:12
@fran-worley early-stage PRs are always welcome
Fran Worley
@fran-worley
May 13 2016 08:13
@solnic cool, I keep running around in circles with this and I'm sure I'm missing something simple!
@fran-worley don't spend too much time on this, if you're stuck just send a PR and we can discuss
Fran Worley
@fran-worley
May 13 2016 08:20
@solnic kinda seeing it as a personal challenge now. I love working in pure ruby :smiley_cat:
Luca Guidi
@jodosha
May 13 2016 08:22
@solnic OMG that is another huge band-aid for AR models callbacks.
I couldn't help myself
this is just ridiculous
@fran-worley I didn't mean to discourage you! :)
Piotr Solnica
@solnic
May 13 2016 08:53
@jodosha the thing is, it doesn't suppress all callbacks, it only suppresses save! call, at least that's what I understood
Fran Worley
@fran-worley
May 13 2016 08:54
@solnic you have no idea how much I am looking forward to replacing AR
Luca Guidi
@jodosha
May 13 2016 08:54
@solnic even worse..
Piotr Solnica
@solnic
May 13 2016 08:58
@fran-worley I did that in the middle of 2013, I barely used AR since then, first I switched to low-level Sequel (not using its AR features), and then I rewrote rom-rb on top of Sequel and started using it. I think with next rom release we're gonna have a pretty serious set of APIs to compete with AR (finally) so adoption should increase
Fran Worley
@fran-worley
May 13 2016 09:00
@solnic that is good to here. I think my biggest concern with changing is gem compatibility as pretty much everything supports AR
Piotr Solnica
@solnic
May 13 2016 09:00
you'd be surprised how easy it is to replace existing AR gems with custom solutions or build new gems
Fran Worley
@fran-worley
May 13 2016 09:01
@solnic I know it just takes time which could be spend on 'new features'. But who needs sleep!
Piotr Solnica
@solnic
May 13 2016 09:01
example: when I realized I can't just use devise with rom I investigated alternatives, turned out they all expect an AR-like behavior, which I didn't like so...after ~2 days of research, I ended up writing a simple auth system on top of warden, took me 45 minutes
Gregory Huczynski
@greghuc
May 13 2016 09:01

Hi @solnic + dry-validation folks.

How does dry-validation play with normalisation of inputs before validation?

For example, I've a JSON rest-api 'post message' endpoint that takes an email and message as input. For api flexibility, I currently trim whitespace from the email value before 'proper' validation (does value match email regex?). So it feels like a two stage process:

I think dry-validation lets me do the validation/coercion part. But how does it fit with the normalisation part? I only want to normalise user inputs I don't control. I wouldn't do this loading an email-serialised-as-string from the DB: would just do Coercion of String(“hello@example.com”) -> Email(“hello@example.com”)

Thanks - trying to make my first baby steps with dry-validation and dry-types :-)

Piotr Solnica
@solnic
May 13 2016 09:01
well, it's the old story of initial cost vs long-term cost
we can (and will) have batteries-included gems that work with rom-rb etc. but they will be 1) simpler 2) extendible w/o monkey-patches
Fran Worley
@fran-worley
May 13 2016 09:02
@solnic I still thank myself that I never went down the devise route. Unfortunately I did get sucked into CanCan for authorisation which is proving to be very difficult to unwind...
Piotr Solnica
@solnic
May 13 2016 09:03
so ie I'm not interested in building things like devise, it's too big, too complex, from my experience devise was one of the biggest reasons why upgrading a rails app to new rails was close-to-impossible (as in, it'd be very risky and time consuming)
I've never seen an auth system with built-in ACL that was done right, not sure if it's even feasible to do haha
Fran Worley
@fran-worley
May 13 2016 09:04
@solnic I reached the same conclusion. Dependencies like carrierwave and cancan have caused me so many headaches.
Piotr Solnica
@solnic
May 13 2016 09:04
@greghuc hey Greg, you can define custom types with custom coercion logic, see here for an example
they can carry not only coercion logic but also constraints that will be used for validation (if you want to)
@fran-worley there are two reasons for that, first of all massive inheritence-based APIs, rather than having re-usable objects gems provided mixins or abstract classes (or both), secondly gems doing too much :)
@greghuc default behavior is to sanitize input based on key definitions and value type definitions, but sneaking in normalization is totally fine, I think it's gonna work well for you. We're currently working on 0.8.0 releases of types and validation so if you see something odd, just report an issue. We want to get to 1.0.0 asap so feedback is very welcome :)
Gregory Huczynski
@greghuc
May 13 2016 09:14

Hi @solnic, thanks for feedback. So am I looking at:

  • JSON API input: dry-validation used to consume " hello@example.com " and return StrippedString("hello@example.com")
  • In domain world, have "Message" object (email + message attributes): dry-types used to represent email with Email type (i.g. string that matches regex). An Email type can be constructed from normal String or StrippedString

I am unclear at which point the supplied 'email' API input value gets converted into an Email type: at the end of input validation, or only when passed into domain "Message" object

Piotr Solnica
@solnic
May 13 2016 09:16
@greghuc oh so you want to coerce a string into a custom type too?
personally I'd advocate against doing so, because you'd be using a validation schema also as a data-to-object-mapper, this is too much. I'd recommend focusing on pure data validation and then using something like a dry-type Struct to build a domain object from safe-and-clean data
structs from dry-types can build objects from hashes so you've got everything you need
Gregory Huczynski
@greghuc
May 13 2016 09:27

@solnic I'm feeling my way forward on a web-app refactor.

I'm wondering about using some custom types in my domain objects. The only custom types that make sense are for Email and Url, and that's really regex enforcement, and ensuring lowercase (Email("hi@example.com == "HI@eXample.com"). Everything else is likely fine in normal ruby types.

But I'm still trying to work out the JSON API input end: that's what requires some extra normalisation. If I'm loading Email or Url types from the DB, I wouldn't need the normalisation, but I would still want to do regex enforcement and lowercasing, which would be encapsulated in the the custom types

Regarding "you'd be using a validation schema also as a data-to-object-mapper, this is too much". It's a hard one to call: I presume dry-validation can coerce a String into a DateTime? That looks a lot like data-to-object mapping ;-)
Gregory Huczynski
@greghuc
May 13 2016 09:45
@solnic I think my underlying issue is how dry-validation and dry-types fit into a web-app (JSON DB-backed API in my case). I kind of want there to be two separate parts:
  • Input validation + coercion: takes user input, normalises it and coerces into simple base types (String, DateTime, and custom types like Url and Email), and returns a hash of these typed attributes. Or errors. dry-validation might do this.
  • Immutable, typed domain objects: a domain object is defined as a set of typed attributes. The object is either constructed from validated-input-hash, or from hash-loaded-from-database. Though hash-loaded-from-database may have had some type coercion (i.e. email stored as string in DB becomes Email type), or that type coercion is built into the domain object. dry-types might work for this
Got to go - back later!
Piotr Solnica
@solnic
May 13 2016 10:01
:laughing:
@greghuc yeah but we're still dealing with ruby primitives
require 'dry-validation'

class Email
  attr_reader :value

  def self.new(input)
    super("#{input}.com")
  end

  def initialize(value)
    @value = value
  end
end

Dry::Types.register_class(Email)

schema = Dry::Validation.Form do
  key(:email).required(type?: Email)
end

puts schema.('email' => 'jane@doe').inspect
@greghuc ^^
output:
#<Dry::Validation::Result output={:email=>#<Email:0x007fe6f2353370 @value="jane@doe.com">} messages={}>
Fran Worley
@fran-worley
May 13 2016 10:09
@solnic is my assumption here correct?
When a predicate is curried, we can get some, all or none of the argument values. The same happens when it is called so we can't make any assumptions about what args we receive and when.
Piotr Solnica
@solnic
May 13 2016 10:15
@fran-worley yeah, you don't know if you've got all args, there's no mechanism for that (at least not yet)
Fran Worley
@fran-worley
May 13 2016 10:16
@solnic think I might have to add that as otherwise I'll be overriding an intentional nil.
Piotr Solnica
@solnic
May 13 2016 10:17
@fran-worley I believe this will turn out to be useful in many places, so feel free to add it
it's a matter of storing arity
ah, failing specs first in dry-rb/dry-logic#13 nice :)
it's easier to TDD when mostly you care about inputs/outputs right? :)
Fran Worley
@fran-worley
May 13 2016 10:20
@solnic thats my plan. What do you think about the AST change?
Piotr Solnica
@solnic
May 13 2016 10:21
I like it, this is a pretty useful piece of info
we're gonna allocate more arrays but that shouldn't hurt esp that we can simplify code in dry-v thanks to this change
Fran Worley
@fran-worley
May 13 2016 10:23
I don't think we can loose the input value from the result ast just yet as it isn't always exactly the same. but for error messages in dry-v it means that you can just focus on the predicate part as that has all the info including the input
Piotr Solnica
@solnic
May 13 2016 10:24
right, the result part of dry-logic is the complicated part
I hope we can improve this over time
I esp don't like that we evaluate input two times :(
Fran Worley
@fran-worley
May 13 2016 10:25
and when you recreate the predicate it causes all sorts of issues as I keep loosing the argument names...
Piotr Solnica
@solnic
May 13 2016 10:29
wow wait, wdym by 'recreate predicate'?
Fran Worley
@fran-worley
May 13 2016 10:30
When you call predicate.curry it intern calls Predicate.new passing in the curried version as the block
Therefore it's not enough to get the argument names on initialisation as calling block.parameters after it has been curried simply returns :rest not the actual parameters
Piotr Solnica
@solnic
May 13 2016 10:31
ah shit
yeah that's what I'm talking about when I say that it'd be great to see MRI getting better FP features rather than some rails-inspired nonsenses
Gregory Huczynski
@greghuc
May 13 2016 10:32
@solnic thanks for the code. Will start on API refactor with dry-validation and dry-type soon.
Piotr Solnica
@solnic
May 13 2016 10:32
well, we have no other choice than to extend predicate with options and store needed data there
Fran Worley
@fran-worley
May 13 2016 10:33
@solnic thats what I figured is it a significant performance hit?
Piotr Solnica
@solnic
May 13 2016 10:34
shouldn't be, we're gonna have more stuff stored in predicates but we don't create predicate instances at runtime in dry-v so
won't affect it too much
the biggest perf gain we can get is to simplify error/hint compilers anyway
Fran Worley
@fran-worley
May 13 2016 10:35
Ok cool. If you try and call an argument without having provided all args should it raise an error? I think at the moment it just fills the unknowns in with nil instead
Piotr Solnica
@solnic
May 13 2016 10:35
we curry predicates when building rules for a schema, then it's just calling predicates with the remaining args
once you get the arity in, you can raise an error
this would be a good improvement, i thought about it already but didn't bother as I was focused more on dry-v
it even crossed my mind to make it auto-curry like in rom relations but thought I won't do it since I don't have an immediate use-case yet
Chris Richards
@cmrichards
May 13 2016 14:52
Hey. Dry-validation will tell me if my form params are valid, but how would I then create an object representing the form that has attributes with the correct types?
Luca Guidi
@jodosha
May 13 2016 16:16
@solnic @timriley @fran-worley @AMHOL @tak1n here's the PR that integrates dry-validation with hanami-validations: hanami/validations#100 :100: - It will land in master next week, the release will happen after dry-v 0.8. Thank you all for your support! :green_heart: :blue_heart: :yellow_heart:
Fran Worley
@fran-worley
May 13 2016 16:41
@jodosha looks great! :thumbsup:
@timriley @solnic Any objections to merging dry-rb/dry-validation#155 into master ?
Luca Guidi
@jodosha
May 13 2016 16:43
:)
Piotr Solnica
@solnic
May 13 2016 16:48
@fran-worley looks good
Fran Worley
@fran-worley
May 13 2016 16:48
@solnic I'd love to have your thoughts on this: dry-rb/dry-logic#13
Piotr Solnica
@solnic
May 13 2016 16:49
I'll check it out later today, busy working atm
Fran Worley
@fran-worley
May 13 2016 16:50
@solnic no worries, I have to say now that I actually understand how the gem works I love it even more. :smiley_cat:
Piotr Solnica
@solnic
May 13 2016 16:51
oh thanks :)
Fran Worley
@fran-worley
May 13 2016 16:51
It really is rather clever!
(not that I was expecting anything less!)
Piotr Solnica
@solnic
May 13 2016 16:52
I'm glad you liked it, I hope it's not that bad-type-of-clever though ;)
Fran Worley
@fran-worley
May 13 2016 16:55
I don't think so, it is a bit hard to follow in places because there are no comments anywhere but I think I get it now!
Piotr Solnica
@solnic
May 13 2016 16:56
sorry about that, I stopped writing yard comments in early-stage projects
the only really complex part is dealing with results, the rest is pretty simple
the good part though, is that we can continue improving it separately from types and validation, as long as ast stays the same we don't have to update validation/types
there are two things we rely on, ast format and result api, in dry-v a schema result implements logic's result api
Fran Worley
@fran-worley
May 13 2016 17:01
@solnic it really was a stroke of genius to separate it. I am starting to use it to process non validation rules.
I had written something myself but it was not nearly as elegant or powerful
Piotr Solnica
@solnic
May 13 2016 17:02
I can't wait to implement dry-v's equivalent in Clojure with 50LOC :laughing:
Piotr Solnica
@solnic
May 13 2016 17:09
@fran-worley yeah this is a general purpose library, I'm pretty sure I will use it in other places too
Don Morrison
@elskwid
May 13 2016 17:09
Now we just need to figure out how to get the big-refactors and other stuff out of Piotr’s head and into issues so we can help. :wink:
Fran Worley
@fran-worley
May 13 2016 17:41
@solnic I think it's safe to say that changing the ast is a breaking change...
Finished in 6.18 seconds (files took 0.9631 seconds to load)
2256 examples, 1040 failures, 68 pending
Piotr Solnica
@solnic
May 13 2016 17:45
@fran-worley yes it is
@fran-worley but this change isn't a big one, should be simple to fix
Phil Schalm
@pnomolos
May 13 2016 18:36
For anyone using dry-types with Rails, dry-types-rails 0.3.0 was just released, which should (hopefully) solve a bunch of issues with using custom types in development :) https://rubygems.org/gems/dry-types-rails/
Thanks to @jeromegn and @AMHOL in making it happen
Andy Holland
@AMHOL
May 13 2016 18:41
:+1: Nice one
Phil Schalm
@pnomolos
May 13 2016 18:42
I am aware of issues if you have tendencies to mash reload and edit really rapidly (likely a race condition) but I don’t know if I’m going to bother fixing that. The better fix is to drink less coffee and calm down ;)
Andy Holland
@AMHOL
May 13 2016 18:42
lol
Probably needs a mutex around the REGISTERED_TYPES stuff?
Phil Schalm
@pnomolos
May 13 2016 18:46
I’m not sure, it actually may be a race condition with respect to the reloading code, since we’re doing the type re-registration out-of-band (only after ActiveSupport::Dependencies has completed its reload cycle)
I’ll try adding a mutex, though, to see if that fixes the problem
Nikita Shilnikov
@flash-gordon
May 13 2016 20:33
@solnic apparently dry-v's cache machinery revealed a bug in jruby Array#hash which leads to collisions. I think it's one more proof that dry-v approach is very fresh :) Btw I tried to get collisions for symbols introduced by calling #hash and found that it's quite likely to have a few collisions on 100k random symbols (different chars & length) on jruby. So probability is actually low but issues are not impossible. Things are better on MRI and rubinius because #hash results has 2 ^ 64 variants against 2 ^ 32 in jruby. I don't think we should do anything about it right know, it's JFYI
oh, and Charles broke Array#hash quite badly in master trying to fix collisions :) Thus dry-v broke jruby eventually
Piotr Solnica
@solnic
May 13 2016 21:37
@flash-gordon thanks for following up on this. I actually did see issues with this on rbx as well
Re caching, I'm trying to identify places where behavior can be pure and cache as much as possible and yes, it is a fresh approach :)
Joe Van Dyk
@joevandyk
May 13 2016 23:28