Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make schema matching easier #18

Open
chancancode opened this issue Aug 1, 2013 · 3 comments
Open

Make schema matching easier #18

chancancode opened this issue Aug 1, 2013 · 3 comments

Comments

@chancancode
Copy link
Owner

Proposed API:

jexp = match({
  id: match(Fixnum).capture_as(:user_id),
  username: match(String).and(->(username){ /a-z0-9/i =~ username }),
  first_name: String,
  last_name: String,
  full_name: ->(full_name, json){ full_name == "#{json['first_name']} #{json['last_name']}" },
  password: match(nothing),
  homepage: /\Ahttps?\:\/\/.*\z/i,
  created_at: match.not(nil),
  updated_at: match.not(nil),
  posts: match({
    id: Fixnum,
    author_id: :user_id,
    title: String,
    tags: match(String).repeated(0..Infinity).or(nil)
  }).fuzzy.repeated(0..Infinity)
})

some_json.should match_json_expression(jexp)

jexp[:user_id] # => 1
  1. match (perhaps need a better name, not sure if this conflicts with other gems) is a factory method that always returns a JsonExpressions::Matcher. Passing a JsonExpressions::Matcher to match is a no-op, otherwise it would wrap that with the appropriate subclass of JsonExpression::Matcher.
  2. JsonExpressions::Matcher defines #and, #or which does what you would expect
  3. JsonExpressions::Matcher also defines #repeated which takes an integer or a integer range which turns its receiver into a JsonExpression::RepetitionMatcher and does what you would expect
  4. anything returns an instance of JsonExpressions::WildcardMatcher which matches anything (including nil), which is basically
  5. nothing returns an instance of `JsonExpression::NothingMatcher, which asserts that key doesn't exists
  6. Calling match, JsonExpressions::Matcher#and and JsonExpressions::Matcher#or with no arguments returns a JsonExpressions::NotProxy which defines a #not method, and that wraps its argument in a JsonExpressions::NotMatcher which negates its results, and then passes this to the original receiver + method
  7. JsonExpression::ArrayMatcher, JsonExpression::ObjectMatcher defines #fuzzy, #exact, #ordered and #unordered, so no more monkey-patching Array and Hash
  8. This would probably be a backwards-incompatible rewrite, We are pre-1.0 after all, so I get to do whatever I want :)

Would like some feedback on this, especially on the naming (fuzzy/exact vs forgiving/strict, etc) and any use cases that I missed.

*Also, please let me know if you expect the match method to conflict with a library you are using today. I'm also open to other suggestions for the top level method that we expose/inject (pattern, expression, expr?)

No ETA. This is probably gonna take some time and tbh it won't be on the top of my priority list for the next while, but I'll do what I can. But now that the spec is here, if you really want it now you can always implement this spec yourself :) (If you do, please pick a different name to avoid confusion)

Thank you for sticking around after I ignored you pull request for so long! (To be clear, I did not abandon the gem – I've been actively using it on Rails 4 / Ruby 2.0 myself, and I'll fix any bugs that prevents it from working correctly, I just haven't been needing these schema oriented functionalities.)

/cc @pda @tdumitrescu @martinstreicher @iangreenleaf @matthew-bb @sricc

@pda
Copy link
Contributor

pda commented Aug 5, 2013

That looks pretty awesome to me.

I like the #fuzzy, #repeated etc methods, too.

What do you think about replacing anything and nothing with match.anything and match.nothing, so that only match needs to be included into the RSpec/whatever namespace?

@chancancode
Copy link
Owner Author

Haven't considered that one, I like the suggestion! In that case the signature of match would have to be def match(*args) ... end to properly distinguish between match(nil) vs match(), which presumably returns a DSLProxy object or something similar which lets you call anything/nothing etc on it. 

I need to think a little but more about the drawbacks of returning proxy objects in general, eg how to report "dangling proxy objects" errors, etc. But I am pretty sure those could be worked out. 

Thanks for the feedback!

Sent from Mailbox for iPhone

On Mon, Aug 5, 2013 at 12:50 PM, Paul Annesley notifications@github.com
wrote:

That looks pretty awesome to me.
I like the #fuzzy, #repeated etc methods, too.

What do you think about replacing anything and nothing with match.anything and match.nothing, so that only match needs to be included into the RSpec/whatever namespace?

Reply to this email directly or view it on GitHub:
#18 (comment)

@Amnesthesia
Copy link

Is this happening?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants