I want to use dry-rails and dry-schema (“safe_params”) in my Ruby on Rails app.
I have the following params for my controller action and I want to define a schema for this:
input = {
"id"=>"asdf",
"collection"=>{
"name"=>"My Collection",
"description"=>"My Description",
"users_attributes"=>{
"0"=>{"user_id"=>"1", "owner"=>"1", "editor"=>"1", "_destroy"=>"0"},
"2"=>{"user_id"=>"223", "owner"=>"0", "editor"=>"0", "_destroy"=>"0"},
"3"=>{"user_id"=>"312332", "owner"=>"1", "editor"=>"1", "_destroy"=>"0"},
"4"=>{"user_id"=>"44", "owner"=>"0", "editor"=>"0", "_destroy"=>"1"},
}
}
}
the issue is “users_attributes”, as it contains an arbitrary list of keys, which again have a well-formed value.
How to do this the smart way?
This is the beast I came up with:
Schema = Dry::Schema.Params do
before(:value_coercer) do |result|
result.to_h.tap do |hash|
if hash[:collection][:users_attributes].nil?
hash[:collection][:users_attributes] = []
else
hash[:collection][:users_attributes] = hash[:collection][:users_attributes].values.map(&:symbolize_keys)
end
# puts "hash[:collection][:users_attributes]: #{hash[:collection][:users_attributes]}"
end
end
after(:rule_applier) do |result|
puts "result: #{result.inspect}"
result.to_h.tap do |hash|
# hash[:collection][:users_attributes] is an array of hashes
# Convert it to a hash of hashes where the key is the index of the array
hash[:collection][:users_attributes] = hash[:collection][:users_attributes].map.with_index do |user_attributes, index|
[index, user_attributes]
end.to_h
# puts "hash[:collection][:users_attributes]: #{hash[:collection][:users_attributes]}"
end
end
required(:id).filled(:string) # uuid
required(:collection).schema do
optional(:name).maybe(:string)
optional(:description).maybe(:string)
optional(:users_attributes).array(:hash) do
optional(:user_id).maybe(:integer)
optional(:owner).maybe(:bool)
optional(:editor).maybe(:bool)
optional(:_destroy).maybe(:bool)
end
end
end