solnic changed the topic of #rom-rb to: Ruby Object Mapper | Mailing List: https://groups.google.com/forum/?fromgroups#!forum/rom-rb | Logs: http://irclog.whitequark.org/rom-rb
CraigBuchek has quit [Read error: Connection reset by peer]
CraigBuchek has joined #rom-rb
<snusnu> warmwaffles: still around?
<snusnu> warmwaffles: there's no support in anima for declaring attributes in separate (well, there kinda is, but you'd typically want to use that differently) .. what i normally do is just simple formatting .. like this:
<snusnu> class Person
<snusnu> include Anima.new(
<snusnu> :name,
<snusnu> :age,
<snusnu> )
<snusnu> end
<snusnu> if you want to a attributes in subclasses, you can do this:
<snusnu> class Student
<snusnu> include anima.add(:snr)
<snusnu> end
<snusnu> warmwaffles: regarding your ducktrap question, there is a way to build "custom" ducktraps … what you need to do, is specify both ways of the coercion, from original to coerced, and from coerced to original .. here's an example taken from my app: http://pastie.org/8441488
<snusnu> dkubb: ^^
<snusnu> dkubb: that might be interesting for you as well, it's not yet documented ducktrap api
<snusnu> warmwaffles: obviously, the above Student class would inherit from Person ;)
<snusnu> warmwaffles: what i like about ducktrap+anima, is that your ruby objects aren't "intertwined" with type (DSL) information .. i realize that both virtus instances and anima instances both don't know about typing .. but imo it's more explicitly stated with anima (no type info in the class definition) .. and with ducktrap, coercion is (and imo should be) external(ly defined)
<snusnu> warmwaffles: i absolutely don't want to talk bad about virtus, it's a great, useful lib! i just happen to believe that within a data mapper context (and that's what i'm most concerned about atm) .. and a certain architecture (immutable all the way down) .. ducktrap+anima separate concerns more explicitly .. and typing information is better suited to be defined on the mapper
<snusnu> warmwaffles: which btw, will most likely be built upon ducktrap .. talking about the future rom-mapper here
<snusnu> warmwaffles: also, eventually, virtus 2.0 will probably be built on top of ducktrap which will in turn incorporate some of the coercions the current coercible supports
<warmwaffles> snusnu: I'm here now
<warmwaffles> snusnu: with ducktype how can I coerce a date that comes in as YYYYMMDD
<snusnu> warmwaffles: if you look at the pastie i linked above, you'd write a ducktrap like that, and within the #forward block, input would be that string, and you'd write code that made sure it returns a date instance .. then you'd write that #inverse block where input is a date instance, and you'd make sure it returns a YYYYMMDD string
<warmwaffles> snusnu: I don't see another snippet other than the one that has include Anima.new
<snusnu> warmwaffles: over time, we want to collect a lot of those common coercions .. kinda like coercible does atm … well, probably they will be implemented in coercible, and ducktrap will be able to use those at some point
<snusnu> warmwaffles: ah ok, here it is: http://irclog.whitequark.org/rom-rb/2013-10-30#5398762;
<warmwaffles> was gonna ask for a gist, but that works ;P
<snusnu> ;)
<warmwaffles> stupid IRSSI coloring, couldn't see the link
<warmwaffles> I see what you mean by the custom now
<warmwaffles> that makes sense
<snusnu> heh yeah, it's hard to overlook that link with that coloring
<snusnu> also, yeah, there are a few builtin ducktraps, but you're always free to write your own custom ones (and assign them to variables for reuse)
<snusnu> the DSL will probably change quite a bit still .. mbj was mostly concerned with getting the internals right so far … i don't really like the current DSL, i'm sure we can come up with something much better
<snusnu> but really, this lib is really really cool (in implementation and concept) .. it has a lot of useful applications in typical (web) code
<warmwaffles> though it makes me a little uneasy to keep using blocks and such in a class like that
<snusnu> you can stick it in front of web facing actions, to act as a sort of parameter sanitizer, with the added benefit, that it will turn your (structurally valid) parameters into proper instances inside your app, suitable for further validation (using mbj/vanguard) … basically oftentimes the models that end up being passed down to rom/axiom too
<snusnu> the cool thing then is, that you can reuse that same ducktrap to create the "external representation" of instances produced by your app .. say on the way in, you deserialize some json string to a hash, turn that into some domain instance using ducktrap .. and on the way out, you take the domain instance, turn it into a proper hash (say, for a form, or json response), and serialize it back to json
<snusnu> all that coercion logic is then defined separately from your domain objects, and your app just needs to keep a few instances of ducktraps around, for any coercion needs
<snusnu> re that uneasy feeling .. think of those ducktraps as the set of instances that are used to do coercion from external to internal representations, and back .. it makes sense that they're separated from domain logic … a little block syntax for defining them doesn't do any harm, keeping a few instances of them around neither
<snusnu> especially when compared to all the nasty code you'd need to write that checks if (potentially deeply) nested input data (from large forms maybe) really conforms to the format your app expects
<warmwaffles> Though I guess it could be considered a factory since it is morphing input and returning output
<snusnu> this is also a very valuable safeguard to set in front of web actions, from a security pov … nuke bad input asap
<snusnu> the way i see it, it is my "coercion + safeguard system" .. i don't trust input from the outside, i want to clearly define the structure it MUST have, and i need to convert that input data to proper internal objects
<snusnu> that's a lot of responsibility, that needs to be handled *somewhere* .. having it done in objects whose sole purpose is that coercion/structural validation, feels right
<snusnu> it allows for "internal" objects (and algorithms) to be coded very offensively … once input data reached some layer inside my app, i *know* it is valid .. no more defensive checks from then on ...
<warmwaffles> the way these libraries are to be used are definitely a departure from what I'm used to
<snusnu> yeah i'm not surprised, we heavily rely on architectures with a small imperative shell and a functional/immutable core (as gary bernhard put it) .. when i saw that presentation, i thought that it really sums up our style neatly … all of the rom code and related gems are written in that style .. we already have gained quite some experience with it, and really like it so far
<snusnu> but tbh, while we've been doing that style for a while now with gems, we haven't yet written a ton of apps using this style .. and like every(?) other ruby programmer, we haven't yet used a *real* datamapper in ruby, because there is none so far ;)
<snusnu> for paid work, i'm working on an app tho, that puts all those lessons to practice, uses all our gems, and i'm really happy with how it turns out … but as you said, it's quite a way from a typical rails/sinatra/padrino/whatever app
<warmwaffles> Is there a way to add a filter to an Axiom::Relation?
<warmwaffles> duh, the relation is enumerable
<snusnu> wdym by filter? ah ok .. yeah it's enumerable .. but a relation exposes relational algrbra ops, like #restrict .. which would probably be closest to what i'd expect a "filter" to be?
<warmwaffles> basically something similar to a WHERE clause
<snusnu> right
<snusnu> that'd be #restrict
<snusnu> new_relation = relation.restrict { |r| r.name.eq('Screw').or(r.city.eq('London')) }
<snusnu> (taken from the dkubb/axiom readme ;)
<warmwaffles> yea I see that line
<warmwaffles> I didn't know what the verb restrict meant
<snusnu> yeah, it's a RA (relational algebra) term … dunno what you'd call a WHERE clause with SQL tho, ain't that a restriction too?
* snusnu is no native english speaker
<warmwaffles> SQL is built on top of relationall algebra
<snusnu> yeah
<warmwaffles> I had to learn it in my databases class, but we didn't cover it in depth
<snusnu> this is probably the best docs (apart from "proper" literature) i've read so far: http://www.quicksort.co.uk/DeeDoc.html .. it's python, "but not" .. it's a python implementation of the D language, a sort of standard for relational algebra languages
<snusnu> axiom's api is closely modelled after that
<snusnu> i remember not getting it at all back at uni .. but my mind wasn't ready for CS when i started it :p
<snusnu> it's actually not really that hard
<warmwaffles> nah, programming language isn't a problem.
<warmwaffles> I float between erlang, ruby, c, and java
postmodern has quit [Quit: Leaving]
irclogger_____ has quit [Remote host closed the connection]
irclogger_ has joined #rom-rb
CraigBuchek has quit [Read error: Connection reset by peer]
CraigBuchek has joined #rom-rb
<warmwaffles> snusnu: you still here?
<dkubb> SQL is similar to RA.. I wouldn't say it's completely based on it, although it probably started that way. it has a bunch of inconsistencies, and a whole bunch of things that got designed-in by committed. it's also not based on sets, but rather multisets/bags in that relations allow duplicates
<dkubb> This book shows how to write SQL in a way that works around many of it's issues: https://amzn.com/1449316409
<warmwaffles> dkubb: what timezone are you in
<dkubb> Pacific
<dkubb> warmwaffles: what about you?
<dkubb> mbj and snusnu are in Europe, which is why they aren't always active in the afternoon/evenings
<dkubb> although snusu has some crazy sleep patterns I have yet to figure out ;)
<warmwaffles> Central
<warmwaffles> I'm in Texas
<dkubb> ahh ok, I'm in British Columbia
<warmwaffles> Ah another cannuck
<warmwaffles> work with a guy that is in Okatoke (sp?)
<warmwaffles> okotoke
<warmwaffles> ah
<warmwaffles> Okotoks
<warmwaffles> there we go
<dkubb> yeah, there's a few of us .. Canada's population is rather small so I know far fewer Canadian programmers than American
<dkubb> I believe California has more people in it than all of Canada
<warmwaffles> heh, yea but man, it beats living in this hot hell hole that is Texas
<warmwaffles> weather is super bipolar here and humid as hell
<dkubb> Come to BC! We'll give you 2 months of snow, 9 months of rain and 1 month of sun every year
<dkubb> actually we had like 3-4 months of sun, which is unusual
<dkubb> and some years we hardly get any snow, at least where I am.. but I'm on the coast, so it's a bit warmer here. in Alberta and some of the provinces in the middle the winters can get really harsh
<warmwaffles> I miss the pacific coast
<warmwaffles> used to live in oregon on the columbia river
<warmwaffles> no where near the ocean, we lived in the rain shadow so we got like 2-3 inches a year in precipitation
<dkubb> I've never heard of the "rain shadow" before
<dkubb> oh I see it's a common thing.. I guess I've never been exposed to the term where I live
<warmwaffles> yea I'm sure if you head more east, you'll see it
snusnu has quit [Quit: Leaving.]
<warmwaffles> there he goes
<warmwaffles> gah I wish axiom coerced the columns
<warmwaffles> damn you immutable objects
<warmwaffles> "columnHeaders": [
<warmwaffles> {
<warmwaffles> "name": string,
<warmwaffles> "dataType": string
<warmwaffles> "columnType": string,
<warmwaffles> }
<warmwaffles> ],
<warmwaffles> "rows": [
<warmwaffles> [
<warmwaffles> string
<warmwaffles> ]
<warmwaffles> ],
<warmwaffles> fuck you google for returning Integers as strings in your JSON output
<warmwaffles> god how I hate you
<dkubb> heh
<dkubb> I probably wouldn't want automagic coercion, but I would add functions that can be used with extend() to coerce it
<dkubb> what we need is a nice way to coerce incoming data
<dkubb> you could always make an enumerator (or an enumerable object) that has an #each method that yields each coerced object
<dkubb> then inject that into the relation
<warmwaffles> Well, honestly I'd like to coerce the objects before it even hits the Relation
<dkubb> a few times in the last year I've created small pipelines of enumerable objects where I inject something into the start of the pipeline, and each step along the way performs one transformation, with the final result what I expect
<warmwaffles> The problem is that our queries and columns are likely to change as time progresses
<warmwaffles> I mean I could march through each of the columns in a data set that will have upwards of 27,000 rows and coerce them
<dkubb> I heard you mentioning virtus earlier
<warmwaffles> yea most of our models are implemented with virtus because it was quick and dirty to slam the hashes in
<dkubb> you could have virtus objects declared for each kind of "row", and let it handle coercion, and then just make sure it responds to #[] before handing it off to axiom
<dkubb> or you could coerce to a hash.. I can't recall if virtus supports #to_hash or #attributes
<dkubb> my biggest problem with ducktrap is just lack of examples. I know snusnu and mbj used it together on a few projects, but it feels like it could be the right approach here, but there's no docs
<dkubb> also I think the interface probably needs a bit of refinement before it clicks
<warmwaffles> The problem with using virtus to define the rows is that the row data will change and the columns could possibly shift depending on how the query is structured
<dkubb> I believe mbj describes it as a way to declare a schema for the data along with a method of transformation into another format
<dkubb> ahh I see, so you're looking at using Hashes to represent each row
<warmwaffles> I honestly don't want to use hashes for rows just because that is really bloaty
<dkubb> because the column names aren't fixed
<warmwaffles> ah
<warmwaffles> that is a great point
<dkubb> hmm..
<warmwaffles> thanks, I'm gonna expand on your hash idea here for a bit
<dkubb> so were you thinking about building a Header for each kind of row?
<warmwaffles> oh hell no
<warmwaffles> lol
<dkubb> heh
<warmwaffles> I'm gonna do the hash idea, and use symbols for keys that way memory isn't wasted
<dkubb> one way to organize the coercion would be to declare a Hash, where the keys are your expected column types, and each value is a proc that handles transformation of that attribute
<dkubb> well not a proc, but something that responds to #call (which could be a proc, but doesn't need to be)
<warmwaffles> yea I was expirimenting with something similar to that
<warmwaffles> ->(value) { value.to_i } or something
<dkubb> then you can dynamically select the propert transformations based on what the rows look like
<dkubb> yeah
<dkubb> it only works if your column names can be made unique
<warmwaffles> they will be unique
<warmwaffles> once I get them coerced and pretty, I can shove them into memcache and keep them there for 12 hours
<warmwaffles> or 24
<dkubb> coercer = Coercible::Coercer.new; transformers = { date: coercer[String].method(:to_date) }
<dkubb> then transformers[name].call(value)
<dkubb> or transformers[name][value] => coerced_value
<dkubb> obviously the keys in the hash would be different, and more pletiful.
mbj has joined #rom-rb
<warmwaffles> oh hello
<dkubb> warmwaffles: this is roughly what I was thinking: https://gist.github.com/dkubb/7228155
<dkubb> warmwaffles: the advantage is that coercion is performed on-demand, rather than having to do it up-front. it could be combined with a stream based json parser to avoid buffering results
<warmwaffles> dkubb: gain, google returns YYYYMMDD so how would I be able to specify Date.strptime(value, '%Y%m%d')
<warmwaffles> rather, how do I define a custom coercer
<warmwaffles> you've been a ton of help man
<dkubb> well, you could declare it as ->(value) { Date.strptime(value, '%Y%m%d') } ... that hash I declare has objects that respond to #[]/#call as the value.. so it wouldn't matter if you use a proc or method objects as I've done here
<dkubb> or you could use Date.method(:parse) which I think works with that format by default
<dkubb> actually, I think coercer may have a to_date method too.. one sec
<warmwaffles> oh derp
<warmwaffles> should have realized that
<dkubb> ok, I've updated that gist with something that works
<warmwaffles> dude this is exactly what I am looking for
<dkubb> sweet
<warmwaffles> plus I learned a ton of new shit today
<warmwaffles> I forgot that Hash can use a proc
<warmwaffles> that makes me super excited
<dkubb> oh you mean the Hash.new argument?
<warmwaffles> yea
<warmwaffles> I assume that's how hash with indifferent access works no?
<dkubb> I'm not sure actually
<dkubb> it's been a while since I looked at the implementation
<warmwaffles> for good reasons ;)
<dkubb> lol
<mbj> dkubb: morning
<dkubb> mbj: good evening
<warmwaffles> 2am here
<dkubb> warmwaffles: in this specific case I actually set the default value for the Hash to a proc, not necessarily setting Hash#default
<dkubb> warmwaffles: it returns a proc that simply passes through the value untouched. I do this to handle keys with no explicit coercion needed, like the name field
<warmwaffles> right
<dkubb> this way you don't have to write any conditional logic to handle explicitly coerced attributes differently
<dkubb> I suppose it's a slight impact on perf, but it's probably negligible and not likely to be the bottleneck
<warmwaffles> well the transformation would be done and then the entire set cached for a bunch of other processes to consume
<warmwaffles> so once the initial coercion is done, the rest is smoother sailing
<dkubb> warmwaffles: here's one more example where it doesn't make any assumptions about what the input type is: https://gist.github.com/dkubb/7228155
<dkubb> warmwaffles: it uses the value class to choose the correct coercion class, and then calls it's to_whatever method
mbj has quit [Ping timeout: 245 seconds]
<warmwaffles> dkubb: so I assume if their is no coercion defined for a key, the default will drop to :to_string
<dkubb> right
mbj has joined #rom-rb
<dkubb> I don't know if coercible has a "to nothing" method
<dkubb> *do nothing
<warmwaffles> I may just not use coercible at all and just define the coercions as I need them
<dkubb> yeah, you can do that too.. the proc as values pattern is probably the most flexible
<warmwaffles> by the way, you've kind of blown my mind for the night and I thought all hope was lost but I have something to atleast show tomorrow
<warmwaffles> err...today
<dkubb> the only reason I like coercible is that it handles some of the common annoying things in ruby
<dkubb> such as the fact that "".to_i is 0
<warmwaffles> ahhaha
<warmwaffles> what is returned by coercible for that ""
<warmwaffles> nil?
<dkubb> an exception I think
<warmwaffles> oh exception
<warmwaffles> nice
<warmwaffles> though...both have their benifits I think
<warmwaffles> apples to oranges
<dkubb> yeah, it depends on the case
<warmwaffles> actually, I may use this coercible now that I think about it
<dkubb> also nil.to_i is 0.. so crazy
<warmwaffles> what
<warmwaffles> the
<dkubb> oh this is interesting: Coercible::Coercer.new[NilClass].to_boolean(nil) -> nil
<warmwaffles> fuck
<warmwaffles> lol
<dkubb> I don't like using #to_i much.. Integer(string) is nicer because at least when the data starts coming in different from what you expect it loudly complains
<dkubb> I don't like silent incorrect coercions.. like mysql does
<dkubb> either pass perfectly or blow up so I can know my assumption about the data was wrong
<mbj> dkubb: I'd love to have a coercion library where the exact coercion can be specified. For example Coerce.from(String, :decimal).to(Integer)
<mbj> dkubb: So I'd not accept "any string that can be coerced to an integer" only the ones I expect.
<mbj> dkubb: This would be *much* sharper.
<mbj> Input format whitelisting.
<dkubb> mbj: yeah, probably even nicer than what coercible does.. which imho is a step in the right direction compared to some of the built-in coercion stuff in ruby
<warmwaffles> but the crazier coercions would need to be easily defined such as googles fucking shenanigans
<mbj> dkubb: Ducktrap needs exactly that feature.
<mbj> dkubb: The point is, coercible is "too permissive" and coerces once it finds a valid path. But ducktrap is for verifing the input is in an excepted format.
<dkubb> mbj: I would like to see a bang and non-bang method, where the first raises when there is a problem and the latter simply passes-through the value if it can't be coerced
<mbj> dkubb: I'd be okay to have a result object. For performance reasons the bang method omits the result object and raises.
<mbj> dkubb: But I'd start with an result object, and sees if the creation of a new object is actually a measurable performance problem.
<mbj> That result object would work like the ducktrap ones: Result#success? Result#output
<warmwaffles> I like the bang method modifying internal state, but not simply for denoting that it raises an exception
<mbj> warmwaffles: I like the convention of the bang method does "dangerous" stuff.
<warmwaffles> non bang, would dup.do_the_thing!
<warmwaffles> ah yes, like an excited program
<warmwaffles> doeeit.now!
<dkubb> I still try to follow this for bang and non-bang methods: http://dablog.rubypal.com/2007/8/15/bang-methods-or-danger-will-rubyist
<warmwaffles> ah
<warmwaffles> I haven't seen this article in a long time
<mbj> warmwaffles: I'm to busy to read the backlog, can you explain your coercion case to me in some short words, maybe ducktrap is what you are looking for.
<warmwaffles> heh, sure, google returns back rows = [[...] .. [...]] and columns [[...] .. [...]]
<warmwaffles> google also retardedly sends back integers as strings
<warmwaffles> sends back dates in varying formats
<warmwaffles> sometimes YYYY-MM-DD and others YYYYMMDD
<mbj> warmwaffles: Sending integers as strings as one advantage: you dont need to think about bitsize in languages ;)
<mbj> warmwaffles: bitsize represenation of integers.
<warmwaffles> that is true
<mbj> warmwaffles: And you map this stuff to ruby objects? Poros?
<warmwaffles> yea, currently just shove the JSON they return into a Virtus object
<mbj> warmwaffles: Or axiom tuples?
<warmwaffles> and then I take the rows and put then into axiom relation
<mbj> dkubb: re your link, its exactly what I was following.
<mbj> dkubb: In all my libs I only have one bang method, and this one is private.
<mbj> dkubb: I dislike to have options, you know.
<mbj> warmwaffles: Do you have a gist with an example?
<mbj> warmwaffles: I mean an input example.
<warmwaffles> mbj, I'm actually considering using ducktrap, but we need to shoehorn this sprint out by friday so it's gonna be on the back burner for this time around
<mbj> warmwaffles: If you give me an example of the input I can create an ducktrap for you.
<dkubb> mbj: it looks like some of the keys in the Hash warmwaffles is accepting may vary, but he needs to perform specific coercions when they do exist
<warmwaffles> oh sure
<mbj> warmwaffles: Most likely you'll need a custom node.
<mbj> warmwaffles: But still the ducktrap approach should work very explicit.
<dkubb> mbj: which is why I pasted the example that has a lookup table mapping the keys to different coercions
<mbj> dkubb: I hate formats where you have to react on key presence.
<warmwaffles> there's you a json dump
<dkubb> mbj: yeah, he doesn't have much of a choice since the data comes from google
<mbj> dkubb: This is inline signalling smell.
<mbj> yeah
<dkubb> lol. let's make everything strings!
<warmwaffles> sometimes I just want to punch the engineer who thought this was a good idea in the face
<mbj> heh
<dkubb> that's one of my pet peeves.. if the format allows for something more precise than a string, use it
<warmwaffles> well see their API is a bit inconsistent as well
<dkubb> this is primitive obsession in a format
<mbj> dkubb: Stings must be the leaves of your "how to interpret your object structure tree" ;)
<warmwaffles> you'll see some are actual integers
<warmwaffles> others are strings
<dkubb> also a reason why I am hyper aware of primitive obsession in code
<mbj> warmwaffles: How does the target relation headers look like?
<mbj> BTW I hate "sprint end dates", if it takes time to make up a good design it takes time.
<dkubb> oh I see what you mean by columnHeaders
<warmwaffles> I coerce the column name [column_header.name.underscore.to_sym, column_header.data_type]
<warmwaffles> yea man
<mbj> It does not make sense to force dirty code into the trunk.
<warmwaffles> mbj: I do too, but I said I'd have something extremely rough to show by friday
<warmwaffles> and I hate falling through with promises
<mbj> warmwaffles, dkubb: I found myself into an interesting observation, its generally a good idea to have a poro mapper around "primitive" input data, and consume that poro mappers interface in later layers.
<warmwaffles> anyways, this is just a small portion of the request, the end request has over 26,000+ rows
<dkubb> warmwaffles: keep in mind this channel is logged. I don't know if any of that info is sensitive, but if it is you'd probably want to delete the gist at some point
<mbj> I did this with very good success in my esarch library, wrapping the elasticsearch data types.
<warmwaffles> I'll nuke this gist once we are done
<warmwaffles> not a problem
<mbj> warmwaffles: What is the target relation headers structure?
<dkubb> yeah, I just want to make sure you don't get in trouble for posting it ;)
<warmwaffles> lol
<warmwaffles> mbj what do you mean?
<warmwaffles> def headers
<warmwaffles> columns.map do |h|
<warmwaffles> type = h.type
<warmwaffles> name = h.name.gsub(/ga:/,'').underscore.to_sym
<warmwaffles> value = [name, type]
<warmwaffles> end
<warmwaffles> end
<mbj> warmwaffles: Axiom relations have headers, (colum name-type tuples)
<warmwaffles> naive implementation
<mbj> warmwaffles: BTW value = [name, type] is superflownous, [name, type] is enough ;)
<warmwaffles> I was doing something there earlier, rubocop would catch that for me
<mbj> warmwaffles: heh
<mbj> warmwaffles: okay I see its an automagically generated header.
<warmwaffles> yea :/
<mbj> warmwaffles: So you'd need an automagically generated ducktrap (not uneasy).
<warmwaffles> That's where dkubb came up with the idea to just create a row of hashes, coerce them and reinsert them into an array in a specific order with the proper headers
<warmwaffles> incredibly memory inefficient and dirty
<mbj> warmwaffles: okay, I'd love to create something for you, but I'm in east afrika in a car currently. My cellphone coverage will drop below 2G soon ;)
<mbj> Drinving into a desert without cellphone towers.
<warmwaffles> haha man it's all right not a biggy
<mbj> warmwaffles: Just make it "correct" first, than try to optimize it.
<warmwaffles> that gist is killed btw
<warmwaffles> exactly
<warmwaffles> and what are you doing in east africa
<mbj> warmwaffles: Ducktrap is VERY inefficient. It creates an in memory representation of all conversion steps and saves this for later inspection.
<mbj> warmwaffles: vaction
<warmwaffles> ah cool man, GET OFF OF IRC
<warmwaffles> my wife would murder me
<mbj> warmwaffles: It could be modified to omit these intermediate representations. But I did not had a use case for this.
<mbj> warmwaffles: Heh, not a problem at all. Just waiting for a build in another console ;)
<warmwaffles> hah, well thanks a ton
<mbj> And hoping traffic jam will result me beeing inside cellphone coverage long enough.
<mbj> dkubb, warmwaffles: On the longterm ducktrap will be AST based, than we can have multiple executors, a "streaming" one (automatically generated based on that AST), and an "history tracking one" (current default behavior)
<mbj> In case the streaming one results in a failure, and you access the history we can always revaluate the AST into an history tracking one.
<warmwaffles> I'd like to be able to mix in fetch_keys etc... with multiple duck traps
<mbj> warmwaffles: So I'll not start this ducktrap now. Unlikely I'll finish it in presence of cellphone internet.
<warmwaffles> mbj: don't worry man, enjoy your vacation
<mbj> warmwaffles: Dkubbs suggestion of transforming will also work.
<mbj> warmwaffles: The idea behind ducktrap is to make these conversations more explicit and durable via a dedicated transformation library.
<mbj> warmwaffles: Also you can combine ducktaps, its a composable transformation algebra like axiom is a transformation algebra for relations.
<warmwaffles> yes, I like code being modified less
<warmwaffles> oh nifty
<mbj> dkubb: Gonna finish the fix for the differ. Acutally not a diff-lcs problem. More mutant producing more than one diff.
<mbj> dkubb: In case of memoized methods the memoizer call was outmitted in the original source.
<mbj> dkubb: This should also fix some noop mutations with memoizers.
<mbj> dkubb: Because def foo; end; memoize :foo, was injected as def foo; end (without memoizer)
<dkubb> ahh cool
<dkubb> no worries on speed. it'll take me a bit before I get most of the other mutations in axiom killed
<mbj> dkubb: Are you using mutant on master?
<dkubb> mbj: yup
<dkubb> mbj: which I think is what devtools uses
<mbj> oky
<warmwaffles> dkubb: wow man, thanks for getting me on that jump start for transformation. Now I actually have something that is useable
<dkubb> warmwaffles: awesome to hear
<warmwaffles> just dumped this into a script to run and it makes me happy, so now I need to improve this some
<warmwaffles> well I think I'll be sleeping around 4pm today ahhaha
<dkubb> sweet. also btw I think you could use COERCER[String].method(:to_date) instead of ->(value) { Date.strptime(value, '%Y%m%d') } too
<dkubb> I guess whichever you find more readable
<warmwaffles> really?
<dkubb> yeah
<warmwaffles> oh dear god
<warmwaffles> YES
<warmwaffles> c[String].method(:to_date).call('20101001')
<warmwaffles> it's been a late night
<dkubb> yeah for me too. I'm going to get some sleep while I can
<warmwaffles> dkubb: any other quick wins you can spot?
<dkubb> warmwaffles: no, it looks pretty good to me
<warmwaffles> awesome, thanks a lot
<mbj> dkubb: Fix pushed.
<mbj> warmwaffles: If you like the stuff in this channel, pls also checkout mutant, https://github.com/mbj/mutant
<mbj> warmwaffles: It helps you to be pretty confident on your code/test relationship.
<warmwaffles> oh this is spiffy,
<warmwaffles> I'll show our team of devs
<mbj> warmwaffles: I'd love more commercial teams adopt it.
<dkubb> yeah mutant rocks
<warmwaffles> Oh my god, this is intense
<mbj> warmwaffles: This is the presentation I gave to some audiences already http://slid.es/markusschirp/mutation-testing
<mbj> warmwaffles: Come up with any question.
<dkubb> mbj: thanks, those changes seemed to fix things. now I have to kill the real mutations ;)
<mbj> dkubb: :D
<mbj> dkubb: I was searching the root cause for a long time.
<warmwaffles> mbj: you should probably add a link to the slideshow in the README
<mbj> warmwaffles: Heh, yeah.
<dkubb> mbj: fwiw, I've been running mutations in axiom using this: bundle exec mutant -Ilib -raxiom --rspec Date#pred Range#to_inclusive Range#overlaps? Time#pred Axiom::Aggregate* Axiom::Algebra* Axiom::Attribute* Axiom::Function* Axiom::Relation* Axiom::Tuple* Axiom::Types::Relation Axiom::Types::Tuple Axiom::Aliasable Axiom::Equalizer Axiom::Evaluator Axiom::Operation* Axiom::Visitable
<dkubb> mbj: I wonder if we can expand the devtools mutant config to allow me to specify a list of selectors to match
<mbj> dkubb: Yeah
<dkubb> mbj: so instead of exclusion, which would be alright too, I can just specify all the classes I care about
<mbj> dkubb: I think mutant should parse the config/mutant.yml by itself.
<mbj> dkubb: And devtools should only instruct mutant about the location of that config file.
<warmwaffles> dkubb: mbj: thanks a ton guys, I really need to head to bed. I'll be hanging around here more
<mbj> warmwaffles: you are welcome!
<mbj> warmwaffles: Just added presentations section to README
<dkubb> I'm off to bed now too. good night!
dkubb has quit [Quit: Linkinus - http://linkinus.com]
mbj has quit [Ping timeout: 272 seconds]
mbj has joined #rom-rb
mbj has quit [Ping timeout: 240 seconds]
mbj has joined #rom-rb
mbj has quit [Ping timeout: 240 seconds]
postmodern has joined #rom-rb
skade has joined #rom-rb
mbj has joined #rom-rb
cored has joined #rom-rb
cored has joined #rom-rb
cored has quit [Changing host]
mbj has quit [Ping timeout: 268 seconds]
snusnu has joined #rom-rb
mbj has joined #rom-rb
cored has quit [Ping timeout: 252 seconds]
snusnu has quit [Quit: Leaving.]
cored has joined #rom-rb
snusnu1 has joined #rom-rb
snusnu1 has quit [Quit: Leaving.]
mbj has quit [Ping timeout: 240 seconds]
snusnu has joined #rom-rb
cored has quit [Ping timeout: 240 seconds]
mbj has joined #rom-rb
cored has joined #rom-rb
cored has joined #rom-rb
mbj has quit [Ping timeout: 240 seconds]
snusnu has quit [Quit: Leaving.]
cored has quit [Ping timeout: 245 seconds]
cored has joined #rom-rb
snusnu has joined #rom-rb
semenlem has joined #rom-rb
semenlem has quit [Excess Flood]
cored has quit [Ping timeout: 240 seconds]
xargoon has quit [Ping timeout: 272 seconds]
snusnu has quit [Quit: Leaving.]
postmodern has quit [Quit: Leaving]
snusnu has joined #rom-rb
snusnu has quit [Quit: Leaving.]
mbj has joined #rom-rb
snusnu has joined #rom-rb
irclogger__ has joined #rom-rb
bf4 has joined #rom-rb
snusnu has quit [Quit: Leaving.]
snusnu has joined #rom-rb
dddtest_d558b has joined #rom-rb
snusnu has quit [Quit: Leaving.]
knowtheory has quit [Quit: Computer has gone to sleep]
knowtheory has joined #rom-rb
snusnu has joined #rom-rb
knowtheory has quit [Quit: Computer has gone to sleep]
knowtheory has joined #rom-rb
knowtheory has quit [Ping timeout: 246 seconds]
CraigBuchek has quit [Quit: CraigBuchek]
knowtheory has joined #rom-rb
jfredett-w has quit [Read error: Connection reset by peer]
CraigBuchek has joined #rom-rb
jfredett has joined #rom-rb
mbj has quit [Ping timeout: 246 seconds]
Eiam has quit [Quit: ╯°□°)╯︵ǝpouǝǝɹɟ]
Eiam has joined #rom-rb
snusnu has quit [Quit: Leaving.]
snusnu has joined #rom-rb
snusnu has quit [Client Quit]
snusnu has joined #rom-rb
snusnu has quit [Quit: Leaving.]
snusnu1 has joined #rom-rb
snusnu1 has quit [Client Quit]
skade has quit [Quit: Computer has gone to sleep.]
mbj has joined #rom-rb
mbj has quit [Read error: Connection reset by peer]
snusnu has joined #rom-rb
mbj has joined #rom-rb
mbj has quit [Read error: Connection reset by peer]
mbj has joined #rom-rb
mbj has quit [Read error: Connection reset by peer]
mbj has joined #rom-rb
mbj has quit [Read error: Connection reset by peer]
knowtheory has quit [Quit: Computer has gone to sleep]
knowtheory has joined #rom-rb
cored has joined #rom-rb
sergeyuspolo has joined #rom-rb
mbj has joined #rom-rb
knowtheory has quit [Ping timeout: 272 seconds]
mbj has quit [Read error: Connection reset by peer]
mbj has joined #rom-rb
sergeyuspolo has quit [Ping timeout: 246 seconds]
mbj has quit [Read error: Connection reset by peer]
mbj has joined #rom-rb
mbj has quit [Read error: Connection reset by peer]
mbj has joined #rom-rb
knowtheory has joined #rom-rb
mbj has quit [Read error: Connection reset by peer]
mbj has joined #rom-rb
dddtest_d558b has quit [Remote host closed the connection]
knowtheory has quit [Quit: Computer has gone to sleep]
knowtheory has joined #rom-rb
mbj has quit [Ping timeout: 240 seconds]
mbj_ has joined #rom-rb
knowtheory has quit [Ping timeout: 272 seconds]
mbj_ has quit [Read error: Connection reset by peer]
knowtheory has joined #rom-rb
mbj has joined #rom-rb
mbj has quit [Ping timeout: 240 seconds]
skade has joined #rom-rb
skade has quit [Client Quit]
knowtheory has quit [Quit: Computer has gone to sleep]
knowtheory has joined #rom-rb
knowtheory has quit [Ping timeout: 246 seconds]
knowtheory has joined #rom-rb
CraigBuchek has quit [Quit: CraigBuchek]
knowtheory has quit [Quit: Computer has gone to sleep]
knowtheory has joined #rom-rb
bf4 has quit [Ping timeout: 240 seconds]
irclogger__ has quit [Ping timeout: 245 seconds]
knowtheory has quit [Ping timeout: 248 seconds]