Rails: What is `sanitize` in Rails? - ruby-on-rails

What does sanitize mean in Rails?
I'm reading through the documentation for CanCanCan. It says:
When using strong_parameters or Rails 4+, you have to sanitize inputs
before saving the record, in actions such as :create and :update.
Then per documentation, it requires adding the below:
load_and_authorize_resource param_method: :my_sanitizer
def my_sanitizer
params.require(:article).permit(:name)
end
Source: https://github.com/CanCanCommunity/cancancan
I've also seen sanitize in the area of SQL queries.
What does sanitize mean actually. Does it just mean to allow something?

The SanitizeHelper module provides a set of methods for scrubbing text of undesired HTML elements. These helper methods extend Action View making them callable within your template files.
data = data.html_safe will just mark string data as 'html_safe' and treat it as such afterwards (Marks a string as trusted safe. It will be inserted into HTML with no additional escaping performed. It is your responsibility to ensure that the string contains no malicious content. This method is equivalent to the raw helper in views. It is recommended that you use sanitize instead of this method. It should never be called on user input.).
Have a look at official api doc
action view sanitize helper

Related

Rails Model method that builds a string of links

I have a method on a model called Photo. I have it finding a selection of things from elsewhere in my app. All I need it to do at the end is to create a string of links that I can then output later on when the method is called on an instance.
My code is:
cars.map { |c| link_to(c.name, c) }.join(" AND ")
But i'm hitting this error:
undefined method `link_to' for #<Photo
Any ideas how to fix this?
link_to is a view helper which means it's only available in Rails views by default because it's a router / request concern.
If you specifically want to use link_to you have to include it or reference it directly.
See this SO answer
include ActionView::Helpers::UrlHelper
...
cars.map { |c| link_to(c.name, c) }.join(" AND ")
There are other ways of getting paths than using link_to that I would recommend you consider:
It's arguable that the Rails team would tell you to use UrlFor as the tip in that link suggests:
Tip: If you need to generate URLs from your models or some other place, then ActionController::UrlFor is what you're looking for. Read on for an introduction. In general, this module should not be included on its own, as it is usually included by url_helpers (as in Rails.application.routes.url_helpers).
UrlFor also allows one to access methods that have been auto-generated from named routes.
class User < ActiveRecord::Base
include Rails.application.routes.url_helpers
def base_uri
# named_route method that uses UrlFor
user_path(self)
end
end
User.find(1).base_uri # => "/users/1"
create your own concern to bring in route helpers via ActionMailer as this article suggests
As you may see if you scroll through other SO questions about including view helpers in models, there is pushback on using router and request -based methods outside of controllers and views because it violates the principles of MVC.
I think your use case can give you some peace of mind about this, but it's worth knowing the water is murky and some people may advise you otherwise.
The traditional Rails wisdom (and what I'm about to give you here) is that models should not be creating HTML. They also shouldn't have methods that return HTML. Creating HTML <a> tags should be done much closer to the user interface: in a view template or maybe in a view helper. One reason is that the particular way the hyperlink should be generated is a concern of the view. (Does it need a nofollow attribute? class attributes? This will change, even from one view to another.) And the model should not have any knowledge of these details.
When you do generate links in the views, then you have access to all the helpers such as link_to.
Instead, as I understand it, a model should be responsible for returning its own data. Maybe in your case that'd be an array of dicts of :label, :url. I.e., pure data that'd be easy to pass to link_to.
Hope that helps!

How to access params hash in lib directory rails 6

In my rails app, I am using Kramdown to parse Markdown. I want to extend the functionality of the convert_a method in the HTML converter. Part of this involves accessing the database, but it is dependent on a parameter in the URL. Because I am not directly calling the method that I am overriding I cannot simply pass the method the params hash. Is there a way to access this hash, or even just get the current URL in a module in the lib directory?
to give a bit more context, the method call is in a helper method here:
# in app/helpers/myhelper.rb
def to_html(text)
Kramdown::Document.new(text, parse_block_html: true).to_custom_html
end
and here is the file in which I override the convert_a:
# in lib/custom_html.rb
class CustomHtml < Kramdown::Converter::Html
def convert_a(el, indent)
# use params[:foo] to make query
format_as_span_html(el.type, el.attr, inner(el, indent))
end
end
Edit:
To give a bit more context on where the overrided method is called. I am not extremely familiar with the Kramdown codebase, however it seems that when to_custom_html is called the following bit of code is run inside of Kramdown.rb:
output, warnings = Converter.const_get(name).convert(#root, #options)
which subsequently calls convert_#{el.type} on the internal kramdown elements.
You can pass additional options in Kramdown::Document#new, so just do something like Kramdown::Document.new(text, my_params: params). Then you can use the #options method of the converter to access your params.

Sanitizing user input for a message box

I am developing a crypto-related application and since those people who deal in crypto will always try some sort of scam or script kiddie "hack" I'd like to figure out the best way to clean up content in user-to-user chat boxes and comments fields.
I don't want any HTML/CSS/JS in there.
I want to leave email addresses, URLs, phone numbers and "normal" text untouched.
Right now I am doing a .gsub(/[^0-9a-zA-Z\#\;\:\-\_\,\.\ ]/i, '') before_save but it removes the newlines.
I tried adding .gsub(/[^0-9a-zA-Z\R\#\;\:\-\_\,\.\ ]/i, '') to make it leave newlines alone but it does not seem to work.
Would prefer not having to add any gems.
Rails has an excellent sanitizer built in, that I would recommend you use instead of trying to figure out your own regular expressions.
See:
http://api.rubyonrails.org/classes/ActionView/Helpers/SanitizeHelper.html
Before you render any user's input out the page wrap it in santize
<%= sanitize #comment.body %>
If you want to sanitize before saving to the database, you can include the helper into your controller
class MyController < ApplicationController
include ActionView::Helpers::SanitizeHelper
def create
content = sanitize(params[:content])
Thing.save(content: content)
end
end

In Rails 5, how access cookies method in a model or helper?

How does one access cookies inside a Rails model or helper?
Trying to dry up some controller methods, I am trying to move multiple controller calls to cookies() into application_helper.rb and/or a model.
What doesn't work in application_helper.rb:
cookies[:foo]
ActionDispatch::Cookies.cookies[:foo]
ActionController.cookies[:foo]
ActionDispatch::Cookies::ChainedCookieJars.cookie[:foo]
All of which result in undefined method 'cookies'
Note: Well-meaning answers that simply regurgitate MVC dogma are mis-placed here... I've architected long enough (decades) to know when coloring outside the MVC lines (if possible) is the better route. But the precise syntax eludes me even after digging through Rails source. This question is prompted by a somewhat complex situation related to, among other things, inconsistent browser handling of cookies in cross-domain, ajax environment that sometimes includes local files (for which Chrome declines to manage cookies).
It's not a good idea :) Models are classes, and they shouldn't be aware of what is happening on a web level, and that's why cookies method is implemented in ActionController, but there's no such implementation in ActionModel or ActionHelper. If you need a cookie value in a model, pass a value from a controller then. This is how it should be done.
As #Vasili mentioned, cookies is only available in controllers. But if you want to access cookies in helpers or models, just pass it as an argument, for example:
helper example:
module ApplicationHelper
def some_helper(given_cookies)
given_cookies[:foo] = 'bar'
end
end
In view:
<%= some_helper(cookies) %>

Rails helper for views and controllers?

I know there are ways to make helpers available to controllers, but that this is generally bad form. How should the following be re-worked to avoid this?
I have a Contacts helper called "fullname" that combines a contact's first and last names.
A layout partial called subheader is rendered in the application layout, and contains this code:
<section id="subheader"><%= #subheader %></section>
The controllers set the value of #subheader.
The issue is that I often want "fullname" in #subheader. But this means accessing the helper from the controller. Should this fullname method reside somewhere else?
With something like fullname I usually just define a method on the model itself.
If the fullname method did some type of HTML formatting then I would keep those parts inside a helper.
Since the title of your question might attract viewers looking for a different answer, I'm going to answer the question of "can I use rails helpers in my controllers"? There are legitimate uses for this, so here's the cleanest way to do so:
In the helpers file, wrap the code you want to access in a model like so:
module HelperModuleName
[helper code here]
end
Wrapping only the code you need to use in your controllers (as opposed to including all helpers using include ApplicationHelper) is a good idea because it reduces the possibility for method name clashes and forces you to be more deliberate about your choice to use helpers in controllers.
Now include the module in your application_controller.rb:
class ApplicationController < ActionController::Base
protect_from_forgery
include HelperModuleName
end

Resources