rubysolo/dentaku

Maybe allow more expressions to be used in PLUCK, similar to what is possible in MAP?

vlazar opened this issue · 1 comments

Current PLUCK function implemented in #221 only allows to get values from hash by property name (same as Rails's pluck).

MAP function OTOH allows more:

calculator.evaluate!('map(users, u, u.address.state)', users: [
  { name: "Bob",  age: 44, address: { state: "CA" } },
  { name: "Jane", age: 27, address: { state: "NE" } }
]) # => ["CA", "NE"]

calculator.evaluate!('map(users, u, u.hobbies[0])', users: [
  { name: "Bob",  age: 44, hobbies: ["guitar", "baseball"] },
  { name: "Jane", age: 27, hobbies: ["drawing", "singing"] }
]) # => ["guitar", "drawing"]

With my naive implementation in 677eee3 the first case also worked with PLUCK:

calculator.evaluate!('pluck(users, address.state)', users: [
  { name: "Bob",  age: 44, address: { state: "CA" } },
  { name: "Jane", age: 27, address: { state: "NE" } }
]) # => ["CA", "NE"]

The second case with u.hobbies[0] was failing however due to naive handling here 677eee3#diff-ed127330f002c385f66a40dd7a996f0bce2a52fa32063f15de1c49b8215d35f8R23

calculator.evaluate!('pluck(users, hobbies[0])', users: [
  { name: "Bob",  age: 44, hobbies: ["guitar", "baseball"] },
  { name: "Jane", age: 27, hobbies: ["drawing", "singing"] }
]) # => NoMethodError: private method `identifier' called for #<Dentaku::AST::Access:0x00007f9da8fa73d0>

That's because Dentaku

  • parses u.address.state as #<Dentaku::AST::Identifier:0x00007fae136e8070 @case_sensitive=nil, @identifier="u.address.state">
  • but parses u.hobbies[0] as #<Dentaku::AST::Access:0x00007fae136f96e0 @structure=#<Dentaku::AST::Identifier:0x00007fae136f97f8 @case_sensitive=nil, @identifier="u.hobbies">, @index=#<Dentaku::AST::Numeric:0x00007fae136f9780 @value=0, @type=:numeric>>

The second argument for PLUCK probably shouldn't be treated as an arbitrary expression, that would most likely be too hard (or not possible) to make it work.

I still wonder if allowing some of of the cases like address.state and hobbies[0] (basically limit the allowed syntax to digging some data from an array of hashes) would make sense?

Some thoughts:

  • allowing things like pluck(users, address.state) can be non obvious, it's more than Rails's pluck allows to do (jus pick a value by key)
  • making things like pluck(users, age > 21) (same as map(users, u, u.age > 21)) to work could be too hard
  • can be confusing, since if someone sees example like pluck(users, address.state) then something like pluck(users, age > 21 and address.state = "CA") would probably be expected to work too?

Gonna close it. I've given this some more thoughts and now I think that a simple PLUCK is enough and actually better, than some weird limited version of MAP, or complex implementation. It's not worth it.