Sanitizing params in Rails
The problem: #
Here is the example of data which POST
from a client to API endpoint:
{
"data": {
"type": "entry",
"attributes": {
"title": " Chassidy Kozey re ",
"content": " \n test n tag and spaces \n another "
}
}
}
In the content
, there are whitespaces in the leading, trailing and, middle.
Expectation: #
- The spaces and the whitespaces should be removed from the leading and trailing.
- Keep the spaces in between only.
What is the whitespace?
- null, horizontal tab, line feed, vertical tab, form feed, carriage return, space.
Rspec #
describe 'POST /api/v1/entry' do
context 'create new entry with spaces' do
it 'sanitize entry params' do
entry_params = Fabricate.to_params(:entry,
title: "Lorem ispsum ",
content: " \nconsectetur adipiscing elit\n")
post api_v1_entry_path, params: json_api_request_body(entry_params)
entry = Entry.first
expect(entry.title).to eq 'Lorem ispsum'
expect(entry.content).to eq 'consectetur adipiscing elit'
end
end
end
In the rspec
if I use single quote instead of double quote then I got that error.
It means the string is escaped while running the test.
So here what is the different between single quote vs double quotes in Ruby?
- Double-quoted easier to read, hard to type.
- Double-quoted strings support interpolation.
https://stackoverflow.com/questions/279270/which-style-of-ruby-string-quoting-do-you-favour https://blog.appsignal.com/2016/12/21/ruby-magic-escaping-in-ruby.html
expected: "consectetur adipiscing elit"
got: " \\nconsectetur adipiscing elit\\n"
(compared using ==)
Then let try to clarify these result again in irb
irb
2.4.0 :001 > '\n'.to_s
=> "\\n"
2.4.0 :002 > "\n".to_s
=> "\n"
2.4.0 :003 >
When use single quote the \n
will be escaped, adding one more forward slash
before.
Implement #
def entry_params
permitted_attributes = %i(title content)
params = deserialized_params(require: [], permit: permitted_attributes)
params[:title].strip!
params[:content]).strip!
params
end
Not stop at this step, let use IRB to play with the string.
2.4.0 :015 > foo = "Lorem \n dolor sit amet a"&.strip!&.delete("\n")
=> nil
2.4.0 :016 > foo = "Lorem \n dolor sit amet a "&.strip!&.delete("\n")
=> "Lorem dolor sit amet a"
2.4.0 :017 > foo = "Lorem \n dolor sit amet a\n"&.strip!&.delete("\n")
=> "Lorem dolor sit amet a"
2.4.0 :018 > foo = "Lorem \n dolor sit amet a"&.strip!&.delete("\n")
=> nil
2.4.0 :019 >
Why it returns nil
?
https://apidock.com/ruby/String/strip%21
Removes leading and trailing whitespace from
str
. Returnsnil
ifstr
was not altered.
What if we try to delete
before strip
? And the final decision is
params[:content]&.strip!
params[:content]&.delete!("\n")
Let combine them:
params[:content]&.strip!&.delete!("\r\n\t")
But here the strip
will return nil
when there is nothing to alter.
Then reverse the delete
and strip
to avoid the nil
Conclusion #
To remove the whitespaces leading and trailing, and keep the spaces in the middle.
params[:content]&.delete!("\r\n\t")&.strip!