<dkubb>
I send tweets with it, hit enter and then realize I mistyped it
snusnu1 has joined #rom-rb
snusnu1 has quit [Quit: Leaving.]
solnic has joined #rom-rb
<solnic>
dkubb: ping
<dkubb>
solnic: pong
solnic has quit [Quit: Leaving...]
solnic has joined #rom-rb
<solnic>
dkubb: I updated relation and session to work with new memory stuff
<solnic>
dkubb: the only thing left is...#update
<dkubb>
ahh ok
<solnic>
but everything else worked perfectly :)
<dkubb>
that's good
<solnic>
can you tell me how update is supposed to work now?
<dkubb>
ok, so update is partially implemented in the memory-adapter
<solnic>
yeah I saw that, I tried to use it but something didn't click right :)
<dkubb>
I'm not super happy yet with the interface
<dkubb>
what I would want is something similar to restrict
<dkubb>
so a simple case first: relation.update(:key => value)
<solnic>
yes please!
<dkubb>
and a more complex one: relation.update { |tuple| ... } the block would have to yield a new tuple, and the materialized relation would implement it as replace(map(&block))
<dkubb>
of course for most other relations it would have to represent a change, so that we could build and ast and translate that to the native datastore query language
<solnic>
right
<dkubb>
solnic: with a restrict, the block basically returns a boolean, but with update the block would have to return an expression that can be evaluated and return a tuple
<dkubb>
well, more accurately in restrict the block returns an expression that can either be evaluated to a boolean
<dkubb>
in this case we want an expression that evaluates to a tuple given another tuple as input
<solnic>
will it support partial updates? as in, will all attributes be required?
<dkubb>
I think it should
<solnic>
ok great
<dkubb>
I think it should allow you to express something that is essentially a noop
<dkubb>
everything from that to a full update
<solnic>
session will use dirty attributes to update
<dkubb>
you should be allowed to say relation.update({}) I guess. I don't know if we should just silently do nothing or raise an exception
<dkubb>
I'd guess we just do nothing
<dkubb>
like with restrict you can technically do relation.restrict { true }
<dkubb>
I just ordered http://amzn.com/1449357849 .. I'm pretty sure the stuff we do with write propagation over relational operations is fairly cutting edge, but I wanted to be sure
jessekempf has joined #rom-rb
<dkubb>
solnic: keep in mind too that conceptually an update can be represented with a delete followed by the insert of the new tuple.. of course it's not convenient, but an update is not a "primitive" operation
<dkubb>
solnic: the main reason update is provided is for efficiency and interface reasons
<dkubb>
I'm talking about at the datastore level.. and the same reasons apply to axiom too
<dkubb>
most of the time an inline update is far more efficient
<dkubb>
jessekempf: thanks for that link. that was an awesome talk
<solnic>
dkubb: yes that works
<dkubb>
jessekempf: I can relate to a lot of that talk. at first I was thinking about relational algebra, and how our foundation for ROM has been studied for 40+ years, and virtually identical to the original theories
<dkubb>
jessekempf: and then I liked how at the end he talked about defect identification, which we're doing on the mutant and metric side of things
<dkubb>
we spend a ton of time measuring our code to make sure it's clean and does what we intend
<solnic>
dkubb: ok I switched to new #update and now in my integration spec in rom-session entire relation gets replaced O_o
<solnic>
dkubb: it's possible the setup is borked though
<dkubb>
solnic: hmm.. yeah, I think #update is still a work in progress. I will work on that after nested relations
<travis-ci>
[travis-ci] rom-rb/rom-session#57 (relation-integration - 864fb1e : Piotr Solnica): The build was broken.
<dkubb>
solnic: the #update work I did is more like a placeholder so I could think about the adapter interface.. it turns out the adapter didn't need it, but other adapters will
<dkubb>
by that I mean, the adapter doesn't need it because the materialized relation itself is handling reads and writes
<solnic>
dkubb: it works in a unit spec...sooooo I guess sth is wrong with my integration spec :)
<dkubb>
solnic: so I looked through my RA books today and identified 4 operations: group/ungroup, wrap/unwrap. the former is related to nesting a relation inside another relation, and the latter is nesting a tuple inside another relation
<dkubb>
solnic: I'm going to implement the group/ungroup first because you can technically still represent a single nested tuple, it'll just be a nested relation with a cardinality of 1
<solnic>
wait
<solnic>
nesting tuple inside another relation?
<dkubb>
yeah
<dkubb>
I wish I could visually represent this easily. lemme see if I can grab a diagram
<dkubb>
I love blambeau's diagrams here. I need to make similar documentation for axiom
<solnic>
nice
<dkubb>
I could probably implement something similar to alf using axiom
<dkubb>
solnic: does this make sense now?
<dkubb>
solnic: for me, the diagram in the ungroup docs makes the most sense
<solnic>
a-ha
<solnic>
got it
<dkubb>
and unwrap too
<solnic>
with those ops we could support loading relationships in a really lovely way
<dkubb>
I know, you could join to another relation, then group it
<solnic>
because tuples would look the same no matter if it was from a join or some embedded structure that a db supports natively (like mongo)
<dkubb>
or if the relation is a m:1 or 1:1 we can use wrap
<solnic>
yeah that too :)
<dkubb>
it's nice to see how well this actually maps to objects
<solnic>
I mean, lots and lots of benefits
<solnic>
yes this is exciting
<dkubb>
there's talk about the relational/object impedence mismatch, but I think what people actually mean when theys say that is: RDBMS implementation/object impedence mismatch
<dkubb>
there's no popular RDBMS that is actually relational top to bottom
<solnic>
hmm yeah
<dkubb>
they borrow some concepts, but then do all sorts of other stuff that goes in a different direction
<solnic>
dkubb: hmm so right now #update actually replaces its relation with a new one
<dkubb>
thankfully there's enough of a subset that can actually support it. the book http://amzn.com/1449316409 goes into all this
<dkubb>
solnic: yeah, like I said, I think #update is probably broken from an implementation pov. I would probably mark functionality based on it as pending for now
<dkubb>
jessekempf: the thing I really liked about that talk, and maybe I'm projecting here, but it reminded me how important it is to focus on fundamentals. sure it's nice to know the API of the latest web framework, but knowing HTTP itself inside and out is probably a better place to prioritize your time
<dkubb>
jessekempf: the implementations change regularly, but the foundational stuff is much more important
<solnic>
dkubb: hmm ok
<solnic>
dkubb: I'll wait then
<dkubb>
solnic: with delete and insert, there's not enough for you?
<dkubb>
solnic: you could always implement your update using those primitives and then swap it out for a more efficient implementation later
<solnic>
ok
<dkubb>
solnic: oh I see, it was implemented using delete and insert. do you have access to the original object, so you can dump the tuple for the original to use in the delete, and then dump the object to use in the insert?
<solnic>
dkubb: I have, in session...
<solnic>
dkubb: I'm gonna override it in session and change sig so it receives object and original tuple
<dkubb>
ahh cool
<dkubb>
in axiom I'll make sure to add support for relation.update(attribute => value) first, because it sounds like that's what you'll need more
<solnic>
yeah it's pretty much critical for rom right now
<dkubb>
the other stuff, relation.update { |tuple| ... something dynamic ... } is probably more for general use. like say if you want to calculate something based on the state of the old tuple
<dkubb>
but I don't suspect ROM will use that too much
<dkubb>
yeah, do what you can for now.. there's no functionality that axiom can add that you can't get from delete then insert. the only benefit is efficiency and more intuitive interface. I don't mean to minimize them, they are certainly important, but it should not be a blocker
<solnic>
dkubb: the easiest way to delete all objects in memory adapter is...?!
<solnic>
dkubb: interesting, new mutant is finding more unkilled mutations in rom-session
<dkubb>
solnic: oh yeah, axiom jumped from 70 to 120 mutations in the last week
<dkubb>
solnic: easiest delete all objects in an adapter? for all relations or one relation? if it's the latter, you can just assign an empty relation to the same 'slot'
<dkubb>
solnic: there's currently no api to iterate over the schema, but I was thinking about this
<travis-ci>
[travis-ci] dkubb/axiom#160 (master - cd2fc29 : Dan Kubb): The build has errored.
mbj has joined #rom-rb
postmodern has quit [Quit: Leaving]
snusnu has joined #rom-rb
snusnu has quit [Read error: No route to host]
snusnu has joined #rom-rb
snusnu1 has joined #rom-rb
snusnu2 has joined #rom-rb
snusnu has quit [Ping timeout: 248 seconds]
snusnu1 has quit [Ping timeout: 276 seconds]
solnic has joined #rom-rb
<solnic>
dkubb: morning
<mbj>
ola
<mbj>
*hola :D
<solnic>
hey mbj
<mbj>
solnic: hola
<solnic>
dkubb: I have an interesting use-case with proxy objects - rom::relation proxies to axiom::relation but there's now rom::session::relation which proxies to rom::relation so...once I removed most of the methods from rom::relation they became unavailable for rom::session::relation :)
<solnic>
I guess I need a proxy setup which allows to proxy to...two objects O_o
<Gibheer>
solnic: is that a good idea?
<solnic>
Gibheer: I have no idea
<solnic>
trying to trick this by overridding respond_to? now :P
<Gibheer>
solnic: just playing rubber duck ;)
<solnic>
but I still have a problem because correct relations aren't wrapped
<solnic>
so for example rom::session#restrict will proxy to axiom::relation and instead of getting back rom::relation it will get back axiom one
<solnic>
which is not what we want
<solnic>
I basically need a multi-level proxy :)
<solnic>
dkubb, mbj: ^^^ ideas?
<Gibheer>
that does not sound like you want that
<solnic>
Gibheer: no, it is totally what I want
<solnic>
well, I'm gonna hack it together inside rom::session::relation and maybe we'll be able to generalize it later (if needed)
solnic has quit [Quit: Leaving...]
solnic has joined #rom-rb
solnic has quit [Quit: Leaving...]
mbj has quit [Ping timeout: 246 seconds]
solnic has joined #rom-rb
mbj has joined #rom-rb
<dkubb>
solnic: that's interesting. I'd like to see a code example so I understand exactly what you mean
solnic has quit [Quit: Leaving...]
solnic has joined #rom-rb
<solnic>
dkubb: oops forgot to make ROM::Relation inherit from Axiom::Relation
<dkubb>
solnic: in SQL Alchemy they have a #one method which is gauranteed to return a single object. if it gets 0 or more than 1 result it raises an exception
<solnic>
dkubb: we had that too
<solnic>
need to re-add it
<dkubb>
although I thought about having it only raise an exception if > 1 is returned, but still allow it to return nil. I could have #one! that raises an exception if it's anything other than 1
<solnic>
dkubb: I'm having issue with rom::relation inheriting from axiom::relation
<dkubb>
I've added this to DM in personal projects and I find myself using it far more often than #first or #last
<solnic>
dkubb: getting "`<module:ROM>': superclass mismatch for class Relation (TypeError)"
<solnic>
after adding ROM::Relation < Axiom::Relation
<dkubb>
because most of the time I specify a query that uses a unique key, and #first kind of implies I want the first result from a list of many.. when in fact my expectation is that I should receive only one. I think #one is more clear in a lot of cases
<dkubb>
solnic: do you define ROM::Relation elsewhere
<solnic>
dkubb: well, yeah, but I fixed it there
<dkubb>
solnic: it's possible you have a bare ROM::Relation somewhere that inherits from Object
<solnic>
maybe I missed a spot
<dkubb>
solnic: just above that place where the line is getting thrown you can do raise ROM::Relation.ancestors.inspect if defined?(ROM::Relation)
<dkubb>
s/line is/error is/
<solnic>
geeez version file
<dkubb>
hehe
<solnic>
:)
<dkubb>
I've been hit by that too
<dkubb>
I always require the version file the very last
<dkubb>
solnic: I find it interesting you're using #<< to insert in ROM::Relation. I need to add that
<dkubb>
solnic: we can do a pass together over ROM::Relation and push-down stuff later, and/or update ROM::Relation to use the same conventions. we need to keep their interfaces in sync so everything just duck-types nicely
<solnic>
ok weird, I was expecting it to just work
<solnic>
getting spec failures now
<solnic>
undefined method `to_ary' for #<#<Class:0x00000003797c70> name="Jane">
<solnic>
wat again
<dkubb>
#to_ary is only going to be available on an Array
<dkubb>
or unless you explicitly define it
<dkubb>
I only add it to stuff that duck-types Array
<solnic>
I have no ideas what's causing that
<solnic>
it didn't happen when rom::relation wasn't inheriting from axiom::relation
<solnic>
ok got it
<solnic>
seems like ROM::Relation#each isn't called
<solnic>
so tuples are being returned
<dkubb>
hmm, as a test try moving that #to_a alias after #each is declared
<solnic>
I don't get it
<solnic>
it says to_a isn't defined
<solnic>
this class includes enumerable
<solnic>
ah wait
<solnic>
proxy removes enumerable methods
<dkubb>
but you're adding them back with include Enumerable
<solnic>
yes
<solnic>
I also define #each
<solnic>
and it is not being called
<solnic>
I think I will revert that whole thing and stick with overridden methods and manual delegation
<solnic>
this proxy magic doesn't seem to be working here
mbj has quit [Ping timeout: 276 seconds]
<dkubb>
yeah, do what you need to, and make the specs pass. I can look at it
<dkubb>
... after. it's likely not something too crazy
<solnic>
I'm confused about those missing methods
<dkubb>
it's certainly not magic. everything behaves in a consistent, repeatable way :P
<solnic>
I can't use my Proxy because it sets ivars after object was initialized so...
<solnic>
I used the word "magic" in good sense here
<dkubb>
I thought it was magic like "works (or does not work) in a way I cannot understand" .. and I know you're capable of understanding it ;P .. it may be that it makes different assumptions than you need it to
<dkubb>
like in the general sense, an Axiom::Proxy doesn't need to wrap and "infect" any of the proxied return values
<dkubb>
I found I couldn't use Proxy with the relational gateway stuff I did in axiom-do-adapter
<dkubb>
I was going to take a second stab at it when I did it again, but for now i probably wouldn't use it in your case
machuga is now known as machuga|away
solnic has quit [Quit: Leaving...]
solnic has joined #rom-rb
<solnic>
dkubb: yeah I know how it works
<solnic>
I'm just confused why methods are gone even though I included Enumerable
<solnic>
Proxy undef those methods but I re-add them so that's weird
<solnic>
ah wait
<solnic>
I can't use proxy geez
<solnic>
I've been there already, my memory sucks :)
<solnic>
meh reverting...
<solnic>
dkubb: so, re #first and #last - this should return a collection
<dkubb>
yeah, in axiom most things are collections
<solnic>
yeah
<dkubb>
although I would consider having #one return a tuple
<solnic>
I will do that now
<solnic>
and add #one
<solnic>
yup
<dkubb>
but otherwise I wanted to keep "closure" .. chaining stuff you get without knowing anything more than it's a relation is beneficial I think
<dkubb>
solnic: do you develop with guard turned on?
<solnic>
dkubb: yup
<dkubb>
solnic: have you got rubocop config turned on?
<dkubb>
my process with rubocop is similar to other metrics. i make the change it recommends unless i disagree strongly with it, and then I update the configuration to exclude that test. anythign with thresholds I'll set to be equal to my worst code with a comment on what I'd like the threshold to be eventually
<dkubb>
I think most of us do the same thing
<dkubb>
I just did a pass over mutant a second ago, which is why I bring it up
<dkubb>
there's still a few problems in mutant, but 80% of the warnings rubocop raised are gone
<solnic>
nice
<solnic>
dkubb: what's the difference between take and first?
<dkubb>
solnic: they are essentially the same operation in axiom
<dkubb>
solnic: actualy, I guess the difference is that first defaults to a limit of 1
<solnic>
that's pretty much what's left for first release of rom-relation
<solnic>
almost identical list is for rom-mapper
<solnic>
I suspect I will finish it all within the next ~7-10 days
<dkubb>
I would probably add a note to add some good examples to the README
<solnic>
shit, of course :)
<solnic>
I forgot
<solnic>
lemme add that
<dkubb>
you need to snusnu-ify it
<solnic>
thanks
<solnic>
hahah
<solnic>
inorite
<dkubb>
snusnu should totally be the gatekeeper for good READMEs. I think he has some awesome ones
<solnic>
yeah he likes to write...code samples :P
kapowaz has quit [Ping timeout: 264 seconds]
<solnic>
btw I think a huge readme is not so great, I'm planning to simplify virtus' readme for example and move a lot of stuff to wiki and user-docs
<dkubb>
I basically like a README to include examples
<dkubb>
I'm removing redundant things install instructions
<dkubb>
I like a description of what it does if it's not clear
<solnic>
yeah but it shouldn't be overwhelming imho
<dkubb>
the funny thing is everyone needs something different from a README, so maybe having a few basic code examples and then having it mostly act as an index to the other docs is the way to go (?)
<solnic>
I'd say it should have the minimum info to get people started with a library
<solnic>
like super basic examples, a few of them only
<dkubb>
I'd like to see which areas of the project are in most need of help
<mbj>
dkubb: pls do so
<mbj>
and add a note we target 100% self coverage :D
<dkubb>
sure
<snusnu>
if i had a mutator wish free, i'd take :blockarg
<snusnu>
blockarg : 8
<snusnu>
rescue : 1
<snusnu>
resbody : 1
<snusnu>
kwbegin : 1
kapowaz has joined #rom-rb
<snusnu>
that's for substation
<snusnu>
mbj: btw, do i understand that output correctly, when i think that once there's *no such output* anymore, the lib actually is fully mutation covered?
<dkubb>
snusnu: no, it just means that mutant isn't really exercising those nodes very well
<dkubb>
snusnu: it means that mutant doesn't do anything special for them. we're using it like a todo list to know which mutators to add next
<dkubb>
snusnu: I'm mostly making a best effort to add new mutators, adding the simplest mutations that come to mind, and I think we should plan to do a second pass looking for more later
<snusnu>
dkubb: ah ok, i thought those were the remaining nodes occurring in the code, that don't have a mutator yet
<dkubb>
snusnu: they have a mutator, but it's *really* simple.. it basically passes through the node, and only mutates it's children
<dkubb>
snusnu: it wouldn't even do something like nil substitution
<snusnu>
dkubb: ah ok, so then, what about some output that would "behave" like i thought the current one would?
<dkubb>
snusnu: every node we know of has a mutator, it falls back to the generic mutator which does the stuff I mentioned
<snusnu>
dkubb: hmm, for some reason i don't seem to get it … you're saying that you're using the current output as a todo list for which mutators to add next .. so once that todo list is empty (for any lib), doesn't that mean that there's no more nodes left in the code, that still miss a mutator?
<snusnu>
dkubb: to be clear, by "for any lib" i mean, let's say substation … so if there's no more "todo notes" left for substation, doesn't that mean substation is actually fully mutation covered, as there are no mutators left on the todo?
<snusnu>
sorry if that sounds dumb :p
theCrab has quit [Read error: Connection reset by peer]
<dkubb>
snusnu: sorry, I'm probably not explaining it very well. lemme start over
<dkubb>
snusnu: ok, so right now parser generates a set of specific nodes. mutant either handles it explictily with a mutator designed for that node, or it passes it through to the generic mutator
<dkubb>
snusnu: the end goal is that mutant will no longer have a generic mutator and every single node will be handled explicitly
<dkubb>
snusnu: when we have explicit mutators for every kind of node we can make sure we target the mutations to that specific kind of node, rather than just doing a few generic mutations
<dkubb>
snusnu: all that list means is that "in this code, the following nodes were found that the generic mutator handled"
<dkubb>
snusnu: mbj and I are running mutant against our own libs, and using that list to prioritize which nodes we add explicit mutators for
<dkubb>
we can't add them all at once, but we want to focus our time on the ones that are most common first
<mbj>
dkubb: good description :D
<dkubb>
mbj: see, I'm starting to get it ;)
<dkubb>
mbj: mutant is really nice and easy to add mutators to. I suspect once we build a community around it we'll see lots of new mutators contributed
<mbj>
yeah
<mbj>
I'm happy with the overall design, need to polish lots of stuff.
<mbj>
Especially self coverage.
<dkubb>
mbj: I think spec coverage is probably most important first. currently it's like 88.74%
<dkubb>
mbj: I added the threshold into spec/spec_helper.rb so that if it drops the build will break
<dkubb>
mbj: we can start to ratchet it up each time we add more code
<snusnu>
ok, so once that list is empty for substation, it means every occurring node is handled by an explicit mutator .. but that doesn't yet mean that there are no more valid mutations in it … because only then will we tackle every specific node to see if there are any valid mutations to add?
<snusnu>
s/mutations/mutators
<dkubb>
snusnu: yeah, there will proabbly always be new valid mutations to discover
<snusnu>
dkubb: yeah, i think i get it now, thx for bearing with me ;)
<mbj>
dkubb: Mutant was very uneasy to fully spec cover
<dkubb>
mbj: yeah, I'm sure it is
<mbj>
Mostly because it was missing self coverage mode from the start.
<mbj>
I normally start with 100% spec/mutation coverage and never lower the bar.
<snusnu>
because it's all about raising the bar, as we know
<snusnu>
:p
<dkubb>
mbj: hmm, I wonder if there would be a mode where we first run simplecov against some code to see what is 100% covered, and then focus mutant only on that
<dkubb>
heh
<mbj>
dkubb: mhh, dunno
<mbj>
lemme add that flexible rspec thing before.
<dkubb>
mbj: then as we get things to 100% coverage, mutant will make sure we stay there
<dkubb>
yeah
<dkubb>
I was just trying to think of some kind of incremental approach