{"id":19312116,"url":"https://github.com/bigcommerce/gruf-commander","last_synced_at":"2025-04-22T15:31:53.348Z","repository":{"id":52419511,"uuid":"116695837","full_name":"bigcommerce/gruf-commander","owner":"bigcommerce","description":"Command/Request library for Gruf request validation","archived":false,"fork":false,"pushed_at":"2021-04-29T19:39:26.000Z","size":36,"stargazers_count":5,"open_issues_count":1,"forks_count":2,"subscribers_count":15,"default_branch":"main","last_synced_at":"2025-04-11T00:41:35.543Z","etag":null,"topics":["cqrs","gruf","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/bigcommerce.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-01-08T15:45:40.000Z","updated_at":"2021-04-22T01:39:11.000Z","dependencies_parsed_at":"2022-09-04T11:00:10.924Z","dependency_job_id":null,"html_url":"https://github.com/bigcommerce/gruf-commander","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bigcommerce%2Fgruf-commander","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bigcommerce%2Fgruf-commander/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bigcommerce%2Fgruf-commander/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bigcommerce%2Fgruf-commander/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bigcommerce","download_url":"https://codeload.github.com/bigcommerce/gruf-commander/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250267399,"owners_count":21402468,"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":["cqrs","gruf","ruby"],"created_at":"2024-11-10T00:32:55.447Z","updated_at":"2025-04-22T15:31:53.023Z","avatar_url":"https://github.com/bigcommerce.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Gruf Commander\n\n[![CircleCI](https://circleci.com/gh/bigcommerce/gruf-commander.svg?style=svg)](https://circleci.com/gh/bigcommerce/gruf-commander) [![Gem Version](https://badge.fury.io/rb/gruf-commander.svg)](https://badge.fury.io/rb/gruf-commander) [![Documentation](https://inch-ci.org/github/bigcommerce/gruf-commander.svg?branch=main)](https://inch-ci.org/github/bigcommerce/gruf-commander?branch=main)\n\nAssists with request/command-style syntax and separated validation layer in [gruf](https://github.com/bigcommerce/gruf)\nrequests.\n\n## Installation\n\nAdd this line to your application's Gemfile:\n\n```ruby\ngem 'gruf-commander'\n```\n\nAnd then execute:\n\n    $ bundle\n\nOr install it yourself as:\n\n    $ gem install gruf-commander\n    \n### Rails \u003c 5 usage\n\nIf you're on a Rails version prior to 3/4, or utilizing ActiveModel \u003c 5, you'll need to install the \n[active_model-errors_details](https://github.com/cowbell/active_model-errors_details) gem.\n\n```ruby\ngem 'active_model-errors_details'\n``` \n\n## Usage\n\nGruf Commander supports the Command/Request design pattern. You create Request classes that perform validation,\nand then submit themselves to a Command. The Command class then performs the business logic by interacting\nwith internal layers of the application, such as the service, DTO, or repository layers.\n\nFirst, in your gruf initializer, add the interceptor:\n\n```ruby\nGruf.configure do |c|\n  c.interceptors.use(Gruf::Commander::RequestValidationInterceptor)\nend\n```\n\nThen you'll create your command and request classes:\n\n```ruby\nclass CreateBoxCommand \u003c Gruf::Commander::Command\n  def call(request)\n    Box.create!(width: request.width, height: request.height)\n  end\nend\n\n\nclass CreateBoxRequest \u003c Gruf::Commander::Request\n  attr_reader :width\n  attr_reader :height\n  \n  validate :validate_width, :validate_height\n  \n  def initialize(width:, height:)\n    @width = width\n    @height = height\n    super(command: CreateBoxCommand.new)\n  end\n  \n  private\n  \n  def validate_width\n    return if @width.to_i \u003e 0    \n    errors.add(:width, :invalid_width, message: 'Please enter a valid width!')\n  end\n  \n  def validate_height\n    return if @height.to_i \u003e 0    \n    errors.add(:height, :invalid_height, message: 'Please enter a valid height!')\n  end\nend\n```\n\nThen, in your gruf controller:\n\n```ruby\ndef create_box\n  request = CreateBoxRequest.new(\n    width: request.message.width.to_i,\n    height: request.message.height.to_i,\n  )\n  box = request.submit!\n  Rpc::CreateBoxResponse.new(\n    box: Rpc::Box.new(height: box.height, width: box.width)\n  )\nend\n```\n\nGruf Commander will automatically handle the validation errors to push back to the grpc server, properly sending an\n`GRPC::InvalidArgument` exception should validation fail.\n\n### Configuration\n\nYou can configure the request validation options:\n\n|Config Name|Description|Default|\n|---|---|---|\n|`invalid_request_error_code`|Sets the gRPC error code sent back on failed validation.|`:invalid_argument`|\n|`invalid_request_app_error_code`|Sets the app error code sent back on failed validation.|`:invalid_request`|\n|`invalid_request_message`|Sets the error message sent back on failed validation.|Invalid Request|\n\n### Dependency Injection\n\nGruf Commander works very well with DI systems such as [dry-rb](http://dry-rb.org/), since Request objects can simply\njust provide accessors to modify their attributes, and commands are simple plain classes that can have no strict \ncontract on initialization.\n\nWe recommend using a DI system (such as dry-rb) to use with Gruf Commander, as it helps with testing and refactoring\nin more complex applications. \n\n## Testing\n\nTests are run via rspec:\n\n```bash\nbundle exec rspec\n```\n\n## License\n\nCopyright (c) 2018-present, BigCommerce Pty. Ltd. All rights reserved \n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated \ndocumentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the \nrights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit \npersons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the \nSoftware.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE \nWARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR \nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR \nOTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbigcommerce%2Fgruf-commander","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbigcommerce%2Fgruf-commander","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbigcommerce%2Fgruf-commander/lists"}