{"id":164,"date":"2014-12-05T17:49:37","date_gmt":"2014-12-05T17:49:37","guid":{"rendered":"https:\/\/redbooth.com\/engineering\/?p=164"},"modified":"2015-07-28T18:24:35","modified_gmt":"2015-07-28T18:24:35","slug":"valid-valid-valid","status":"publish","type":"post","link":"https:\/\/redbooth.com\/engineering\/technical\/valid-valid-valid","title":{"rendered":"valid , valid? , valid!"},"content":{"rendered":"<p>In this article, you\u2019ll learn some interesting Ruby validation techniques. We\u2019ll drive you trhough input and output validation inside ruby applications, the good and bads and some possible solutions.<\/p>\n<p>You are probably already familiar with the different validation layers present in Rails (or other ruby frameworks). Viewing them from the request point of view we have something like:<\/p>\n<p><a href=\"https:\/\/s3.amazonaws.com\/wordpress-production\/wp-content\/uploads\/sites\/7\/2014\/11\/validation-current.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-166\" style=\"padding: 0;\" src=\"https:\/\/s3.amazonaws.com\/wordpress-production\/wp-content\/uploads\/sites\/7\/2014\/11\/validation-current-1024x460.png\" alt=\"validation-current\" width=\"1024\" height=\"460\" srcset=\"https:\/\/wordpress-production.s3.amazonaws.com\/wp-content\/uploads\/sites\/7\/2014\/11\/validation-current-1024x460.png 1024w, https:\/\/wordpress-production.s3.amazonaws.com\/wp-content\/uploads\/sites\/7\/2014\/11\/validation-current-300x134.png 300w, https:\/\/wordpress-production.s3.amazonaws.com\/wp-content\/uploads\/sites\/7\/2014\/11\/validation-current.png 1432w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/p>\n<p>Rack validation gives you content type validation and some extra validations like files and body in multipart requests.<\/p>\n<p>Rails versions &gt;4 comes with strong params, which gives you the ability to define which of the input params are required or allowed, and with a not very exhaustive feature you can define the param type choosing between a short list of types.<\/p>\n<p>Model validations in rails come from the `ActiveModel::Validations` module, they are awesome and you can do almost any kind of format, inclusion, uniqueness or custom validation there.<\/p>\n<p>Aside from rails we also have:<\/p>\n<ul>\n<li>Lotus Validations: <a title=\"Lotus Validations\" href=\"http:\/\/lucaguidi.com\/2014\/10\/23\/introducing-lotus-validations.html\" target=\"_blank\">http:\/\/lucaguidi.com\/2014\/10\/23\/introducing-lotus-validations.html<\/a><\/li>\n<li>Sinatra Validations: <a title=\"Sinatra Validations\" href=\"http:\/\/lucaguidi.com\/2014\/10\/23\/introducing-lotus-validations.html\" target=\"_blank\">https:\/\/github.com\/mattt\/sinatra-param<\/a><\/li>\n<\/ul>\n<h2>What is missing<\/h2>\n<p>Let\u2019s put it into perspective: if we draw the previous diagram matching sizes with how accurate the validation is in a regular Rails app we will have something like:<\/p>\n<p><a href=\"https:\/\/s3.amazonaws.com\/wordpress-production\/wp-content\/uploads\/sites\/7\/2014\/11\/validation-perspective.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-167\" style=\"padding: 0;\" src=\"https:\/\/s3.amazonaws.com\/wordpress-production\/wp-content\/uploads\/sites\/7\/2014\/11\/validation-perspective-1024x371.png\" alt=\"validation-perspective\" width=\"1024\" height=\"371\" srcset=\"https:\/\/wordpress-production.s3.amazonaws.com\/wp-content\/uploads\/sites\/7\/2014\/11\/validation-perspective-1024x371.png 1024w, https:\/\/wordpress-production.s3.amazonaws.com\/wp-content\/uploads\/sites\/7\/2014\/11\/validation-perspective-300x108.png 300w, https:\/\/wordpress-production.s3.amazonaws.com\/wp-content\/uploads\/sites\/7\/2014\/11\/validation-perspective.png 1424w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/p>\n<p>This makes sense, as you are protecting the most precious attribute of your app, the persisted data. But let\u2019s think about it from the performance and the security point of view: all kind of validation is good for your app health and the sooner you make it the sooner you will be able to stop the request processing, saving machine resources and adding previous layer security in your app.<\/p>\n<p>So, why not move those sizes around and have a bigger param validation layer? why not include format, types, relations and all the power of the `ActiveModel::Validations` in the controller param validator layer?<\/p>\n<p>This idea jumped into our minds during the new API architecture design, and we came up with something called ParamValidators. The idea is dead simple: use plain ruby objects with `ActiveModel::Validations` as service objects to validate and extract params before the controller uses them.<\/p>\n<h2>Param Validators<\/h2>\n<p>Let\u2019s start with the base object handling the logic methods to build param validator ruby objects:<\/p>\n<pre># app\/validators\/param_validator\/base.rb\r\n \r\nmodule ParamsValidator\r\n  class Base\r\n    include ActiveModel::Validations\r\n    \r\n    # Memoizes the accessor atrributes in the @attributes variable to be able\r\n    # to list them and access them\r\n    #\r\n    def self.attr_accessor(*vars)\r\n      @attributes ||= []\r\n      @attributes.concat vars\r\n      super(*vars)\r\n    end\r\n  \r\n    # Accessor method to the memoized attrubutes setted by the attr_accessor method\r\n    #\r\n    # @return [Array(Symbols)]\r\n    def self.attributes\r\n      @attributes ||= []\r\n \r\n      super_attributes = superclass.attributes if superclass &amp;&amp; superclass.respond_to?(:attributes)\r\n      (super_attributes || []) + @attributes\r\n    end\r\n    \r\n    # Initializes the param validator object with the given controller params\r\n    # HashwithIndifferentAccess object and feeds any defined attribute with the given param key\r\n    # if they exists\r\n    #\r\n    def initialize(params = {})\r\n      params.each do |key, value|\r\n        attribute?(key) &amp;&amp; send(\"#{key}=\", value)\r\n      end\r\n    end\r\n    \r\n    # Alias for the attributes class method\r\n    #\r\n    # @return [Array(Symbol)]\r\n    def attributes\r\n      self.class.attributes\r\n    end\r\n    \r\n    # Returns the given attibutes validated and parsed if needed\r\n    # to be used in the controller\r\n    # \r\n    # @return [HashWithIndifferentAccess]\r\n    def to_params\r\n      ::HashWithIndifferentAccess.new(attributes_hash)\r\n    end\r\n \r\n    private\r\n    \r\n    # Whenever the given they is a valid attribute or not\r\n    #\r\n    # @return [Boolean]\r\n    def attribute?(key)\r\n      self.class.instance_methods.include? key.to_sym\r\n    end\r\n \r\n    # Return the attributes of the validator filtered by\r\n    # attributes has been set in the initializer with params\r\n    #\r\n    # @return [Array]\r\n    def settled_attributes\r\n      instance_vars = self.instance_variables.map do |attr|\r\n        attr.to_s[1..-1].to_sym\r\n      end\r\n \r\n      instance_vars &amp; attributes\r\n    end\r\n \r\n    # Return a hash with the attributes and values that\r\n    # will be sent to the controller\r\n    #\r\n    # @return [Hash] {attribute1: value, attribute2: value}\r\n    def attributes_hash\r\n      settled_attributes.inject({}) do |out, attribute|\r\n        value = public_send(attribute)\r\n        out[attribute] = value\r\n        out\r\n      end\r\n    end\r\n  end\r\nend\r\n<\/pre>\n<p>In this basic base object we take care of three things:<\/p>\n<ul>\n<li>Collect the defined attributes with `attr_accessor` (allowed ones)<\/li>\n<li>Initialize them with the given param keys<\/li>\n<li>Provide a method to return a `HashWithIndifferentAccess` after assignation validation and parsing.<\/li>\n<\/ul>\n<p>Now we are able to create objects like:<\/p>\n<pre># app\/validators\/param_validator\/fancy.rb\r\n \r\nclass ParamValidator::Fancy &lt; ParamValidator::Base\r\n  attr_accessor :user_id, :fancy_name, :fancy_description\r\n  \r\n  validates :user_id, :fancy_name, presence: true\r\n  validates :user_id, integer: true\r\nend\r\n\r\n\r\nHere we are setting some allowed params with `attr_accessor`, some required ones with the presence validator and we could add any other param validator as format, size or type just using the regular `ActiveModel::Validation` methods or any other custom validation build in top of that.\r\n\r\nBut let\u2019s see how we can use this in the controller. The first thing we built is the ParamsFor module allowing any controller including the module to easily use the param validator objects.\r\n\r\n<code>\r\n# lib\/params_for.rb\r\n \r\nrequire 'active_support\/concern'\r\n \r\nmodule ParamsFor\r\n  extend ActiveSupport::Concern\r\n \r\n  private\r\n  \r\n  # Strong params checker\r\n  #\r\n  # @param name [Symbol] camelcased validator class name\r\n  # @param options [Hash] optional\r\n  # @option options [Boolean] :class class of the validator\r\n  # @return [Hash]\r\n  def params_for(name, options = {})\r\n    instance_var_name = \"@#{name.to_s}_params\"\r\n    instance_var = instance_variable_get(instance_var_name)\r\n    return instance_var if instance_var.present?\r\n \r\n    if options[:class]\r\n      validator_klass = options[:class]\r\n    else\r\n      validator_name = \"ParamsValidator::#{name.to_s.classify}\"\r\n      validator_klass = validator_name.constantize\r\n    end\r\n \r\n    validator = validator_klass.new(params)\r\n    \r\n    unless validator.valid?\r\n      render status: :bad_request, json: validator.errors.to_json and return \r\n    end\r\n \r\n    instance_variable_set(instance_var_name, validator.to_params)\r\n  end\r\nend\r\n<\/code><\/pre>\n<p>This is just a meta function allowing you to instantiate a `ParamValidator` object with the current request params, validate it (rendering a :bad_request response with the json errors if is not valid) and memoizing the validated, filtered and parsed Hash. In short, it allows you to easily use `ParamValidator` objects in a controller just like this:<\/p>\n<pre># app\/controllers\/fancy_controller.rb\r\n \r\nclass Fancycontroller &lt; ApplicationController\r\n  include ParamsFor\r\n  \r\n  # Creates a Fancy object by checking and validating params \r\n  # before that\r\n  #\r\n  def create\r\n    ...\r\n    @fancy = Fancy.new(fancy_params)  \r\n    ...\r\n  end\r\n  \r\n  protected\r\n  \r\n  # Strong params delegated to ParamValidator::Fancy\r\n  # and memoized in @fancy_params var returned by this method\r\n  #\r\n  # @return [HashwithIndifferentAccess]\r\n  def fancy_params\r\n    params_for :fancy  \r\n  end\r\nend\r\n<\/pre>\n<h2>Wrap up<\/h2>\n<p>In the last few paragraphs we explored the different validation types and responsibilities in rails applications, understood their use cases and detected the missing parts.<\/p>\n<p>After that we proposed a partial solution to the problem by redifining the architectural way the input validation is built in current rails applications.<\/p>\n<h2>Links<\/h2>\n<p>We have an open source project <a href=\"https:\/\/github.com\/andresbravog\/params_for\" target=\"_blank\">here<\/a> where you can participate or expose your ideas about the `ParamValidator` thing.<\/p>\n<p>Thanks and happy coding.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this article, you\u2019ll learn some interesting Ruby validation techniques. We\u2019ll drive you trhough input and output validation inside ruby applications, the good and bads and some possible solutions. You are probably already familiar with the different validation layers present in Rails (or other ruby frameworks). Viewing them from the request point of view we <a class=\"read-more\" href=\"https:\/\/redbooth.com\/engineering\/technical\/valid-valid-valid\">&hellip;&nbsp;<span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":49,"featured_media":165,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[27,24,7],"tags":[32,11,28,31],"class_list":["post-164","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-platform","category-ruby","category-technical","tag-params_for","tag-rails","tag-ruby-2","tag-validations"],"_links":{"self":[{"href":"https:\/\/redbooth.com\/engineering\/wp-json\/wp\/v2\/posts\/164","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/redbooth.com\/engineering\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/redbooth.com\/engineering\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/redbooth.com\/engineering\/wp-json\/wp\/v2\/users\/49"}],"replies":[{"embeddable":true,"href":"https:\/\/redbooth.com\/engineering\/wp-json\/wp\/v2\/comments?post=164"}],"version-history":[{"count":0,"href":"https:\/\/redbooth.com\/engineering\/wp-json\/wp\/v2\/posts\/164\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/redbooth.com\/engineering\/wp-json\/wp\/v2\/media\/165"}],"wp:attachment":[{"href":"https:\/\/redbooth.com\/engineering\/wp-json\/wp\/v2\/media?parent=164"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/redbooth.com\/engineering\/wp-json\/wp\/v2\/categories?post=164"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/redbooth.com\/engineering\/wp-json\/wp\/v2\/tags?post=164"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}