{"title":"Params","description":"","section":"guides/controllers","version":"v1.5","path":"guides/controllers/params","canonical_url":"https://amberframework.org/docs/v1.5/guides/controllers/params","markdown_url":"https://amberframework.org/docs/v1.5/guides/controllers/params.md","inherited":true,"content_markdown":"# Params\n\n## Introduction\n\nWhen building a web application, at some point you will want to access data sent from a client. Amber makes the data received from an HTTP Request available to the controller via the params object. \n\nThe params object parses the data from the request, this includes:\n\n1. Query String parameters: the query string is everything after \"?\" in the URL. \n2. Form input parameters: these are sent as HTML form posts\n3. Route URL parameters: route url parameters are defined within the resource url.\n\n## Basic Usage\n\nRegular String parameters can be accessed using the following methods. Please note\n\n```crystal\nparams[:key] # requires that the param exists already\nparams[:key]? # does not require that the param exists\n```\n\nTo set a param use the following syntax\n\n```crystal\nparams[:key] = \"My String\"\n```\n\nPlease note that while params accepts a Symbol key to be passed, it will be converted to a String automatically. For example the following two statements are equivalent.\n\n```crystal\nparams[:key] # => \"My String\"\nparams[\"key\"] # => \"My String\"\n```\n\nThe params object will only contain entries that have been successfully validated using the Validation API. If you do not use the Validation API this will return an empty Hash.\n\n```crystal\nparams.to_h\n```\n\nTo access the entire raw / non-validated params hash:\n\n```crystal\nparams.to_unsafe_h\n```\n\n## Array Parameters\n\nThe params object is not limited to one-dimensional keys and values. It can contain nested arrays and hashes. To send an array of values, append an empty pair of square brackets \"[]\" to the key name\n\nIf you need to get an array of params from the query:\n\n```text\n?brand[]=brand1&brand[]=brand2&brand[]=brand3\n```\n\nTo retrieve all possible values for a key:\n\n```crystal\nparams.fetch_all(\"brand[]\") # => { \"brand[]\" => [\"brand1\", \"brand2\", \"brand3\"] }\n```\n> The value of params[\"brand[]\"] will now be [\"brand1\", \"brand2\", \"brand3\"]. Note that parameter values are always strings; Amber makes no attempt to guess or cast the type.\n\n## JSON Parameters\n\nWhen writing a Web Service application that accepts JSON data, the application most likely will need to parse the incoming JSON payload. When the \"Content-Type\" header of your request is set to \"application/json\", Amber will automatically load your parameters into the params object, which you can access as you would normally.\n\n## Routing Parameters\n\nAny other parameters defined by the routing, such as :id, will also be available in the `params` object. As an example, consider a listing of clients where the list can show either active or inactive clients. We can add a route which captures the `:status` parameter in a \"pretty\" URL:\n\n```crystal\nget '/clients/:status' => ClientsController, :index\n```\n\nIn this case, when a user opens the URL `/clients/active`, `params[:status]` will be set to \"active\"\n\n## Validating request parameters\n\nPerforming validations at the params level can save your application from performing operations deemed to be invalid due to input params. Having parameter validations in place prevents errors due to invalid input and increases the security of your application in general.\n\nValidating params and erroring early in the request lifecycle frees resources for the next request sooner, adds a layer of security and prevents invalid data from reaching the backend processes.\n\nAmber attempts to alleviate the issues that come with invalid parameters and provides a `params` object to all controllers which contains a built-in `validation` method.\n\n### Benefits\n\n- Expression and explicitness about the parameters the model expects.\n- Security by whitelisting only the parameters allowed per action.\n- Data correctness to prevent invalid inputs to propagate in the system.\n\n### Example Usage\n\n```crystal\nclass UsersController < ApplicationController\n  def create\n    user = User.new(user_params.validate!)\n    \n    if user.save\n      redirect_to action: :index, flash: {:success => \"Created user successfully!\"}\n    else\n      redirect_to action: :index, flash: {:error => \"Could not create user!\"}\n    end\n  end\n  \n  def user_params\n    params.validation do\n     required(:name, \"Your First Name is missing!\") { |p| p.name? & !p.name.empty? }\n     required(:email, \"Your email address is invalid!\") { |p| p.email? & p.size.between? 1..10 }\n     required(:last_name) { |p| p.last_name? }\n    end\n  end\nend\n```\n\n### Validation API\n\n`#validation` Setup validation rules to be performed.\n\n- Use `#required(field)` to define required fields.\n- Use `#optional(field)` to define optional fields.\n\n```crystal\nparams.validation do\n  required(:email) { |p| p.url? }\n  optional(:age)\nend\n```\n\n`#validate!` Input must be valid otherwise raises an error. If valid, returns a hash of validated params otherwise raises `Validator::ValidationFailed` which contains the failed validaton error messages.\n\n```crystal\nuser = User.new params.validate!\n```\n\n`#valid?` Returns true if all params are valid or false otherwise. \n\n```crystal\nunless params.valid?\n  response.puts {errors: params.errors}.to_json\n  response.status_code 400\nend\n```\n\n`#errors` Returns an array of errors for the invalid inputs. This array of errors is populated after running `#validate!` or `#valid?`.\n\n```crystal\nparams.errors\n```\n\n### Field Validation Rules\n\nAmber has extended the Crystal String and Number classes with additional methods to assist with better validation.\n\n| String                      | Number          |\n|-----------------------------|-----------------|\n| `str?`                        | `positive?`       |\n| `email?`                      | `negative?`       |\n| `domain?`                     | `zero?`           |\n| `url?`                        | `div?(n)`         |\n| `ipv4?`                       | `above?(n)`       |\n| `ipv6?`                       | `below?(n)`       |\n| `mac_address?`                | `lt?(num)`        |\n| `hex_color?`                  | `self?(num)`      |\n| `hex?`                        | `lteq?(num)`      |\n| `alpha?(locale = \"en-US\")`    | `between?(range)` |\n| `numeric?`                    | `gteq?(num)`      |\n| `alphanum?(locale = \"en-US\")` |                 |\n| `md5?`                        |                 |\n| `base64?`                    |                 |\n| `slug?`                       |                 |\n| `lower?`                      |                 |\n| `upper?`                      |                 |\n| `credit_card?`                |                 |\n| `phone?(locale = \"en-US\")`    |                 |\n| `excludes?(value)`            |                 |\n| `time_string?`                |                 |`\n\n### Organizing validations\n\nWith Amber parameter validation, it's easy to keep your code organized:\n\n```crystal\nclass UsersController < ApplicationController\n  include UserParams\n\n  def create\n    unless UserParams.create.valid?\n      response.puts {errors: params.errors}.to_json\n      response.status_code 400\n    end\n\n    user = User.new UserParams.create.validate!\n    user.save!\n\n    @client = Client.new\n    redirect_to :index\n  end\n\n  # Define parameters per actions\n  def update\n    unless UserParams.update.valid?\n      response.puts {errors: params.errors}.to_json\n      response.status_code 400\n    end\n\n    user = User.new UserParams.update.validate!\n    user.save!\n\n    redirect_to :index\n  end\nend\n```"}