1

I'm posting:

{'a': 1, 'b': 2}

where key a is always required and key b is optional. How do I require a and permit b using Rails strong params syntax? params.require(:a).permit(:b) doesn't work...

duhaime
  • 25,611
  • 17
  • 169
  • 224

2 Answers2

2

You're falling victim to a common beginner misconception.

The role of ActionController::Parameters#require is not to validate the presence of parameters - it's to bail early if the structure of the parameters doesn't match the expected input at all. Validations are typically done by the model in Rails.

For example when you have the typical Rails parameters whitelist:

def thing_parameters
  params.require(:thing)
        .permit(:foo, :bar, :baz)
end

There is no meaning in continuing to process the request and trying to update/create a thing if params[:thing] is nil. Therefore we bail early and a return a 400 Bad Request status code.

max
  • 96,212
  • 14
  • 104
  • 165
  • I mean if the controller bails if the data doesn't have a shape, it's implicitly validating the shape of the data ya? I understand we might use a different term to refer to this validation, but it's still a form of validation – duhaime Mar 30 '23 at 19:21
  • Not really. It's main role is to avoid nil errors, not to ensure the consistency of the data. It's really just `#fetch` with a different exception class - so its used to slice hashes. It's completely useless for providing user feedback and all the other things you would want when validating data. – max Mar 31 '23 at 11:13
  • I disagree, if the controller bails when the data doesn't have a shape, it is ensuring the consistency of the data with respect to the aspects of the data it checks. But this is just semantics. – duhaime Apr 03 '23 at 21:53
  • Yeah, but require still isn't relevant in the context of "I want X to be optional but Y, Z should be required" since it will raise an exception on Y before you get to Z. While you could rescue these exceptions and aggregate them its still a broken idea since exceptions are for exeptional events and someone forgetting to fill in a form field is mundane and not exceptional. That's why it doesn't really have anything to do with validation in practice. – max Apr 04 '23 at 12:10
0

I believe that you can solve with other way, using dry validation

require 'dry-validation'

class TableContract < Dry::Validation::Contract
  params do
    required(:a).filled(:bool)

    optional(:b).maybe(:string)
  end
end

now you can use that contract from your controller

TableContract.new.call( a: params[:a], b: params[:b])

more information: https://dry-rb.org/gems/dry-validation/1.8/

rnewed_user
  • 1,386
  • 7
  • 13