These are chat archives for dry-rb/chat

28th
Jun 2016
Janko Marohnić
@janko-m
Jun 28 2016 06:29
I'm trying to make Shrine easy to use with dry-transaction and dry-validation, but I'm pretty new to the dry-rb world.
Tim Riley
@timriley
Jun 28 2016 06:30
Cool! Do you have any questions atm?
Janko Marohnić
@janko-m
Jun 28 2016 06:31
When you're using dry-validation for validating fields of an existing record, do you somehow first sync the attributes from that record
Tim Riley
@timriley
Jun 28 2016 06:31
That’ll depend on how you want to use it from your app.
I usually have a validation schema per-form.
And when it’s an “edit” form, it’ll mean that the pre-existing data (that I care about for that form) should be present.
No “sync” though. Just that the pre-existing data has been fetched in order to render the form, and then when that form is posted, that’s when the data will be sent through, and the dry-v schema will see it.
Janko Marohnić
@janko-m
Jun 28 2016 06:33
Aha, I see, makes sense. Sorry, I have a lot of questions, but trying to organize them in my head.
Tim Riley
@timriley
Jun 28 2016 06:33
np
Janko Marohnić
@janko-m
Jun 28 2016 06:35
So, I'm assuming that in dry-rb you're declaring entities by inheriting from Dry::Types::Struct, correct? Is the construct of attr_accessors like user.name = part of dry-rb? Because It seems that dry-types doesn't provide these accessors
Tim Riley
@timriley
Jun 28 2016 06:36
That’s kinda the opposite of how you’d work with these gems.
Firstly, you don’t actually have to make your own entity classes
if you’re working with e.g. rom via rom-repository, you’ll get plain structs back by default
and if that’s enough for your app, then that’s fine
of course, you can define your own entity classes and have them used for return results from your repos
but the pattern we recommend is that you do not mutate those objects
and rom-rb supports this by separating queries from commands
so if you get some objects back from a query, changing them in place isn’t what you’d want to do to write back to the database anyway
to do that, you make new input for a rom command (which can be set up for you via rom-repo or it can be an explicitly defined standalone command) and then call the command with that input
(a command being an object that is configured to create/update/delete for a particular table in your DB)
Janko Marohnić
@janko-m
Jun 28 2016 06:39
Aha, I see, is this then the general idea?
result = schema.call(params[:photo])
if result.success?
  photo = Photo.new(result.output)
  Repository.persist(photo)
end
I mean, you wrap it in dry-transaction of course.
Tim Riley
@timriley
Jun 28 2016 06:40
kinda. I wouldn’t bother wrapping the schema output in an entity though
Here’s a typical command object as we build them:
Janko Marohnić
@janko-m
Jun 28 2016 06:40
Aaa, ok, I see
Tim Riley
@timriley
Jun 28 2016 06:40
Entities don’t really have any play in places like this, IMO
Janko Marohnić
@janko-m
Jun 28 2016 06:41
Ok, I understand now
My next question is, when using dry-transaction and ROM, is there a way to detect that a column has changed, and then after persisting do something in a separate dry-transaction step based on that information?
Tim Riley
@timriley
Jun 28 2016 06:43
That I am not 100% sure about. It might be worth asking this over in rom-rb/chat. It could be something that’ll be part of the new “changesets” feature that @solnic has been working on.
Anyway, you could always handle this manually, too. What sort of thing are you envisioning being in this extra transaction step?
Janko Marohnić
@janko-m
Jun 28 2016 06:47
So, in Shrine's case, when an attachment has been changed, you want to delete the old attachment
So that there are no orphan files on your storage
Tim Riley
@timriley
Jun 28 2016 06:48
Right
Janko Marohnić
@janko-m
Jun 28 2016 06:49
And then in the step after persisting (it has to be after, so that the record is already saved with the new attachment), I want to delete the old file. However, I'm not able to figure out how to do it in the functional style that dry-transaction has
Tim Riley
@timriley
Jun 28 2016 06:51
Well, we’d need to make sure the return value from the operation to save the changes has the information we want.
Janko Marohnić
@janko-m
Jun 28 2016 06:51
It's not only that, if the attachment has changed, I also want to trigger a background job which does processing and saves the processed files to the column. But only if the column has changed. Or only if a new file was passed in the params
Tim Riley
@timriley
Jun 28 2016 06:51
This is something that you can handle within your application code.
It’s where I’d start with it, anyway… and see if there is a common abstraction to be discovered.
Perhaps the return value that includes both the previous attrs and new, or something like that.
but anyway, I have a hunch that soon-to-be-included-in-rom-rb “changesets” could help with this
Janko Marohnić
@janko-m
Jun 28 2016 06:55
So it's not something that would be done in a dry-transaction step?
Tim Riley
@timriley
Jun 28 2016 06:55
Well, with dry-transaction you get one object that gets passed around
output/input/output, etc.
Janko Marohnić
@janko-m
Jun 28 2016 06:55
Aaa, ok, I see
Tim Riley
@timriley
Jun 28 2016 06:55
what I was suggesting there is that for this to work as a dry-transaction step, the input that it works with would have to have enough info for it to make a decision
Janko Marohnić
@janko-m
Jun 28 2016 06:55
So maybe this fits dry-transaction, just not the same pipeline
Tim Riley
@timriley
Jun 28 2016 06:55
about whether to save or not
so that’s one way
another way could be for the “save” transaction step to make this determination
so it could include that info in its output
it could have an object that includes some sort of image_changes method/methods that the subsequent step could query
anyway, either way, that work needs to be done somewhere
so to put steps like this into a pipeline, we would just have to make sure there is enough data being passed around for them to work
the other direction you could take this is for a “context” object to be used as the interchange object (like https://github.com/collectiveidea/interactor), but I think that’s probably a bad idea
at least for it to be built in to dry-transaction
if as an application author you want to do it, that’s your decision
Better to design objects that are appropriate for your domain and fit your own requirements
Janko Marohnić
@janko-m
Jun 28 2016 07:00
What do you mean by this last sentence?
Hannes Nevalainen
@kwando
Jun 28 2016 07:00
@timriley I have had som luck with an application specific context object
Tim Riley
@timriley
Jun 28 2016 07:01
"Better to design objects that are appropriate for your domain and fit your own requirements”? Well, I’d think it’d mean something like making the output some kind of object that is specific to your application’s own data types and the kinds of commands etc. that need to work with them
So if you’re working with blog posts, perhaps building your own UpdatedBlogPost object or something, something which can tell any other users of that object whether images associated with that post have been changed...
Janko Marohnić
@janko-m
Jun 28 2016 07:02
Ok, thank you for the idea
Tim Riley
@timriley
Jun 28 2016 07:02
I have only mused about this in my head from time to time, @janko-m, haven’t actually built anything like that, just so you know :)
@kwando oh? How does that look?
Hannes Nevalainen
@kwando
Jun 28 2016 07:03
class MyContext
  include Anima.new(:current_user, :input)
end
@timriley Basically something like that ^^
Tim Riley
@timriley
Jun 28 2016 07:04
Cool, right.
^ @janko-m that’s kinda what I mean with designing an object to fit your domain. In @kwando’s case, he wants to reference the current user across a set of operations, I’m guessing :)
Hannes Nevalainen
@kwando
Jun 28 2016 07:05
Yes, current_user is something I usually need
Tim Riley
@timriley
Jun 28 2016 07:05
@kwando are you using this with dry-transaction? Just checking that you’re also aware of http://dry-rb.org/gems/dry-transaction/basic-usage/#passing-additional-step-arguments?
Janko Marohnić
@janko-m
Jun 28 2016 07:05
@timriley It still really helps a lot. Because even though it's my priority to make Shrine easy to work in "dry-rb"-style, I'm still very new to these concepts, so it helps a lot to talk to someone who is familiar with dry-rb and ROM
Hannes Nevalainen
@kwando
Jun 28 2016 07:06
@timriley yes, I'm using it with dry-t
and while on the subject, please bring back otherwise to the result_matcher =P
Tim Riley
@timriley
Jun 28 2016 07:06
Anyway, I haven’t done this enough in my own applications to be able to identify some key shortcut that could be moved up into the gems… which is why I’ve mostly just been rambling through some ideas here @janko-m :grimacing:
@kwando heh! I’d be happy to consider it… especially since I’m working on it right now. What sort of things do you want an otherwise for?
I’m building custom matchers support. But I’ve kept the limitation that only one matched case ever gets executed.
I suppose I could drop that and then you could build your own “otherwise” pretty easily.
Janko Marohnić
@janko-m
Jun 28 2016 07:09
@timriley I'm confident we'll figure something out, I'll definitely ask for feedback once I come up with something. If I managed to solve (or at least I think) so many hard problems of handling file uploads in Shrine, and in my opinion kept a good design, I should be able to make it work :)
Tim Riley
@timriley
Jun 28 2016 07:10
@janko-m IMO, a good first step for making Shrine workable in dry-rb-style apps would be to extract any key operations it offers into independent, callable objects
or otherwise make them easy to access/work with outside of any single integration
Hannes Nevalainen
@kwando
Jun 28 2016 07:11
My specific use case atm is to use a transaction in a web action.. basically I want to to render HTTP 500 for every failure that I specifically don't "catch"
Tim Riley
@timriley
Jun 28 2016 07:12
I think you could do this with the new feature I’ve added.
dry-rb/dry-result_matcher#6
Janko Marohnić
@janko-m
Jun 28 2016 07:12
Yes, it's just that it's so much callbacky/dirty-tracking type of functionality that I found it very hard to design it in callable objects, and that it's still not difficult to use. However, it just means I have to rethink things :)
Tim Riley
@timriley
Jun 28 2016 07:12
@kwando you build up your own matcher object with your own “cases”. Each one has a proc to act as a matcher/resolver.
So in your case (he he) you could provide an “otherwise” case whose matcher just checks that it’s an error of any kind.
And if you put m.otherwise last in your matcher block, it’ll work.
@janko-m couldn’t you build upwards from standalone callable objects and have your dirty-tracking integrations etc. use them?
Hannes Nevalainen
@kwando
Jun 28 2016 07:14
@timriley oh, I'll have to look into that. Thx for the tip!
Tim Riley
@timriley
Jun 28 2016 07:14
I’m not familiar with shrine design challenges, feel free to ignore :)
@kwando np! The only thing I don’t like in what I just suggested is having the position of the match block be so important… but to make that better we’d need to somehow let the match cases know about each other...
Hannes Nevalainen
@kwando
Jun 28 2016 07:21
@timriley I'm still exploring how I wanna use all this stuff, pretty sure a few paths I'm following right now will lead to dark places.. but who knows =P
Tim Riley
@timriley
Jun 28 2016 07:21
haha!
I’d love to see what things you come up with (if it’s possible for you to share)
Janko Marohnić
@janko-m
Jun 28 2016 07:43
@timriley Yeah, this is exactly how I will try to think, in terms of callbable objects, even if all the force in the world is pulling me towards callbacks. Originally I had dry-rb and Trailblazer in mind, but I was thinking "what if only this one thing was in callbacks?". It's so hard to start thinking in another way :)
Tim Riley
@timriley
Jun 28 2016 07:43
Yeah, I hear you. This is exactly why at Icelab we decided to move entirely away from Rails rather than trying to lay a sane architecture over the top of it.
Because it still has all these dangerous “conveniences” that may draw you back in.
Piotr Solnica
@solnic
Jun 28 2016 08:40
@janko-m @timriley if we need to trigger additional actions when an attachment is changing then it defo requires the new changeset API as it’s gonna give you info about fields that will be changed in the db when you commit transaction, and since we’re dealing with many things that can fail here, using dry-transaction sounds pretty reasonable. Shrine could provide its own transaction step that allows proper error handling and triggering actions in external systems and that would be it. We can either provide a very “tight” integration or just provide simple-enough APIs so that people can bake that into their apps without much effort (I’d probably prefer the latter)
Daniel Sandbecker
@daniels
Jun 28 2016 09:25
Sorry for repeating myself, but is there a way to specify that a schema should be applied to the value of a key only if the value is filled (or only if the value is not nil)? I.e. I want to accept an empty hash or nil, but fail on a filled hash that doesn't conform to my schema.
Piotr Solnica
@solnic
Jun 28 2016 09:33
@daniels u on master?
Daniel Sandbecker
@daniels
Jun 28 2016 09:37
@solnic I can be - I haven't switched my project yet, but am investigating what I can do with master now.
Piotr Solnica
@solnic
Jun 28 2016 09:37
@daniels oh don’t, unless you really wanna check it out :D
it needs types and logic from master too
Daniel Sandbecker
@daniels
Jun 28 2016 09:41
@solnic Yes, I made sure (this time) to fetch all the dry-* dependencies from master before starting my exploration. (I had some other trouble using 0.7.4 - I couldn't combine predicates in the way I expected.)
Piotr Solnica
@solnic
Jun 28 2016 09:42
there are plenty of bug fixes in latest dry-v and types
Piotr Solnica
@solnic
Jun 28 2016 12:38
https://github.com/zverok/time_math2 this is freaking awesome
Tim Riley
@timriley
Jun 28 2016 12:38
Yeah! We found an excuse to use it just today too. So happy :)
Piotr Solnica
@solnic
Jun 28 2016 12:39
the fact you can build up an object for later re-use is great
totally inline with dry-rb philosophy
Tim Riley
@timriley
Jun 28 2016 12:41
Yeah. Functions!
Very clever design.
AS ~1.3x slower
Hannes Nevalainen
@kwando
Jun 28 2016 13:21
finally! Thx for sharing time_math2!
I've been searching for a non-AS library doing something like that! <3
Rolf Bjaanes
@rolfb
Jun 28 2016 13:25
@timriley great talk at reddotrubyconf, especially the answer to the question at the end
Tim Riley
@timriley
Jun 28 2016 13:40
@rolfb thanks! :)
Russell Edens
@rx
Jun 28 2016 13:42
@timriley ditto - just watched it, nice job, nice to see an end to end example
Steve
@dnd
Jun 28 2016 15:32
I'm trying to experiment with dry-types, and am getting an undefined method 'try' for a Dry::Types::Struct I tried creating. Is that a method dry-types is expecting to be defined somewhere else?
Steve
@dnd
Jun 28 2016 15:40
it turns out dry-rb/dry-types@861c0b2 fixes the issue. I had to pull from master to get it. Is there a next scheduled release of the dry-types gem?
Piotr Solnica
@solnic
Jun 28 2016 15:45
@dnd I can release it on Friday
there are no blockers, only one pending nice-to-have
Steve
@dnd
Jun 28 2016 15:48
@solnic cool, thanks
^^^^ :+1:^^^^ :bow:
Tim Riley
@timriley
Jun 28 2016 21:22
I suppose I would upvote that ;)
Tim Riley
@timriley
Jun 28 2016 23:20
@solnic do you really reckon we could rename -result_matcher to -matcher?
Piotr Solnica
@solnic
Jun 28 2016 23:56
@timriley yeah I think it would be nicer
Tim Riley
@timriley
Jun 28 2016 23:59
I think this release is the right time then.
-matcher certainly better reflects its broader capabilities.