{"id":15747596,"url":"https://github.com/kachick/eqq","last_synced_at":"2025-03-13T13:32:13.453Z","repository":{"id":37780035,"uuid":"372654166","full_name":"kachick/eqq","owner":"kachick","description":"Pattern objects builder","archived":true,"fork":false,"pushed_at":"2024-09-09T04:48:30.000Z","size":413,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-07T00:38:16.041Z","etag":null,"topics":["condition","functional","pattern","ruby"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kachick.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2021-05-31T23:52:27.000Z","updated_at":"2024-09-09T04:51:02.000Z","dependencies_parsed_at":"2024-02-12T02:37:56.463Z","dependency_job_id":"d279de70-a4ea-432d-871a-9ddf82854187","html_url":"https://github.com/kachick/eqq","commit_stats":{"total_commits":248,"total_committers":4,"mean_commits":62.0,"dds":0.4193548387096774,"last_synced_commit":"051ca3bed59358b226c3d34937ffff820e88fa19"},"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kachick%2Feqq","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kachick%2Feqq/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kachick%2Feqq/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kachick%2Feqq/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kachick","download_url":"https://codeload.github.com/kachick/eqq/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243414504,"owners_count":20287133,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["condition","functional","pattern","ruby"],"created_at":"2024-10-04T05:21:04.238Z","updated_at":"2025-03-13T13:32:13.111Z","avatar_url":"https://github.com/kachick.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# eqq\n\n![Build Status](https://github.com/kachick/eqq/actions/workflows/test_behaviors.yml/badge.svg?branch=main)\n[![Gem Version](https://badge.fury.io/rb/eqq.svg)](http://badge.fury.io/rb/eqq)\n\n- _**This repository is archived**_\n- _**No longer maintained**_\n- _**Registered gem remains for now**_\n\nPattern objects builder\n\n## Usage\n\nRequire Ruby 3.2 or higher\n\nAdd below code into your Gemfile\n\n```ruby\ngem 'eqq', '~\u003e 0.1.1'\n```\n\n### Overview\n\n```ruby\nrequire 'eqq'\n\n[4.2, 42, 42.0, 420].grep(Eqq.AND(Integer, 20..50)) #=\u003e [42]\n[42, nil, true, false, '', 0].grep(Eqq.BOOLEAN) #=\u003e [true, false]\n[42, [], {}, 'string', Object.new, nil].grep(Eqq.CAN(:to_h)) #=\u003e [[], {}, nil]\n\npattern = Eqq.build do\n  OR(AND(Float, 20..50), Integer)\nend\n\np pattern #=\u003e \"OR(AND(Float, 20..50), Integer)\"\n[4.2, 42, 42.0, 420].grep(pattern) #=\u003e [42, 42.0, 420]\n\ninverted = Eqq.NOT(pattern)\np inverted #=\u003e \"NOT(OR(AND(Float, 20..50), Integer))\"\n[4.2, 42, 42.0, 420].grep(inverted) #=\u003e [4.2]\n\nEqq.SEND(:all?, pattern) === [4.2, 42, 42.0, 420] #=\u003e false\nEqq.SEND(:any?, pattern) === [4.2, 42, 42.0, 420] #=\u003e true\n\nret_in_case = (\n  case 42\n  when pattern\n    'Should be matched here! :)'\n  when inverted\n    'Should not be matched here! :\u003c'\n  else\n    'Should not be matched here too! :\u003c'\n  end\n)\n\np ret_in_case #=\u003e Should be matched here! :)\n\nret_in_case = (\n  case 4.2\n  when pattern\n    'Should not be matched here! :\u003c'\n  when inverted\n    'Should be matched here! :)'\n  else\n    'Should not be matched here too! :\u003c'\n  end\n)\n\np ret_in_case #=\u003e Should be matched here! :)\n\nclass MyClass\n  include Eqq::Buildable\n\n  def example\n    [4.2, 42, 42.0, 420].grep(OR(AND(Float, 20..50), Integer))\n  end\nend\nMyClass.new.example #=\u003e [42, 42.0, 420]\n```\n\n### Explanation\n\nAll products can be called as `pattern === other`.\n\nThis signature will fit in most Ruby code.\n\n- `case ~ when` syntax\n- Enumerable#grep\n- Enumerable#grep_v\n- Enumerable#all?\n- Enumerable#any?\n- Enumerable#none?\n- Enumerable#one?\n- Enumerable#slice_after\n- Enumerable#slice_before\n\nThey can take this interface as the `pattern`.\n\nAnd you already saw. All of patterns can be mixed with other patterns as a parts.\nReuse as you wish!\n\n### Builders\n\n- OR(*patterns) - Product returns `true` when matched even one pattern\n- AND(*patterns) - Product returns `true` when matched all patterns\n- NOT(pattern) - Product returns `true` when not matched the pattern\n- CAN(*method_names) - Product returns `true` when it has all of the methods (checked with `respond_to?`)\n- RESCUE(exception_class/module, pattern) - Product returns `true` when the pattern raises the exception\n- QUIET(*patterns) - Product returns `true` when all patterns did not raise any exception\n- EQ(object) - Product returns `true` when matched with `#==`\n- SAME(object) - Product returns `true` when matched with `#equal?`\n- SEND(name, pattern) - Basically provided for Enumerable\n- BOOLEAN() - Product returns `true` when matched to `true` or `false`\n- NIL() - Product returns `true` when matched to `nil` (Not consider `nil?`)\n- ANYTHING() - Product returns `true`, always `true`\n- NEVER() - Product returns `false`, always `false`\n- XOR(pattern1, pattern2) - Product returns `true` when matched one of the pattern, when matched both returns `false`\n- NAND(*patterns) - Product is an inverted `AND`\n- NOR(*patterns) - Product is an inverted `OR`\n\n### Best fit for RSpec's `satisfy` matcher too\n\nAll builders actually generate a `Proc (lambda)` instance.\nThe signature will fit for RSpec's built-in [\"satisfy\" matcher](https://relishapp.com/rspec/rspec-expectations/v/3-10/docs/built-in-matchers/satisfy-matcher) too.\n\n```ruby\nRSpec.describe RSpec::Matchers::BuiltIn::Satisfy do\n  let(:product) { Eqq.AND(Integer, 24..42) }\n\n  it 'perfectly works' do\n    expect(23).not_to satisfy(\u0026product)\n    expect(24).to satisfy(\u0026product)\n    expect(24.0).not_to satisfy(\u0026product)\n    expect(42).to satisfy(\u0026product)\n    expect(42.0).not_to satisfy(\u0026product)\n    expect(43).not_to satisfy(\u0026product)\n  end\nend\n```\n\n### Use builders without receiver specifying\n\nWhen you felt annoy to write `Eqq` in many place, some ways exist.\n\n- `Eqq.build(\u0026block)` - In the block scope, all builder methods can be used without receiver\n- `extend Eqq::Buildable` - In the class/module, all builders can be used as class methods\n- `include Eqq::Buildable` - In the class/module, all builders can be used as instance methods\n\n## Links\n\n- [Repository](https://github.com/kachick/eqq)\n\n## NOTE\n\n- [\"eqq\" is the implementation name of \"#===\" in CRuby](https://github.com/ruby/ruby/blob/2a685da1fcd928530509e99f5edb4117bc377994/range.c#L1859)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkachick%2Feqq","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkachick%2Feqq","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkachick%2Feqq/lists"}