<%= debug(controller) %> produces unreadable output - ruby-on-rails

In one of my templates I want to take a closer look at the controller object using the debug() helper.
It is said to produce YAML suitable for HTML output.
Running <%= debug(controller) %> does, however, not produce anything I call readable.
It begins with:
#<ClubsController:0x104467378 #_request=#<ActionController::Request:0x104467648 #accepts=[#<Mime::Type:0x101f50f30 #synonyms=["application/xhtml+xml"],
and goes on like that...
Any ideas on how to get some info about the object?

The debug helper is primarily intended to be used with objects that provide an implementation of to_yaml (such as ActiveRecord models). If the object passed doesn't respond to to_yaml (as is the case with passing a controller object in your example) then debug gives you the result from calling inspect on that object.

I saw your comment #thenduks answer.
Actually there is a method:
controller.controller_name
that returns the name of the controller.

What's not readable about that? It's the standard ruby inspection syntax... If you really need something 'more readable' then you'll have to write a method on your controller (temporarily, most likely) that simply exposes it's instance variables in another format.
Perhaps it would help if you noted what you want to see in the controller instance.

Related

Why does ActionView's "select_tag" escape the HTML in its "options" argument when called directly?

So I've been going through the very poor documentation that exists for ActionView, particularly a method called select_tag that just exists when called from view files. Supposedly, it's called like this:
select_tag name, option_tags, options
The documentation says nothing at all about the name, very little about the options, and describes the option_tags only through examples that treat it as an opaque value that must be obtained from other functions.
As always, the only way to learn anything about Rails is to reverse-engineer it.
So I tried running it directly from a Rails console, which is tricky because Ruby doesn't let you call methods that are defined in modules unless you create a class and an object first:
class H
include ActionView::Helpers::FormOptionsHelper
include ActionView::Helpers::FormTagHelper
end
H.new.options_for_select ["foo","bar"]
The above usage of options_for_select comes from actual code that somebody else wrote. The return value is a string:
"<option value=\"foo\">foo</option>\n<option value=\"bar\">bar</option>"
So apparently, you're supposed to pass the return value from option_for_select (or one of the many other related functions that introduce complications I don't want to talk about such as generating HTML tags from ActiveRecord objects) as the option_tag parameter of select_tag. Except if you copy that string to your clipboard and paste it directly into a function call, it doesn't do what you'd expect:
H.new.select_tag :my_name, "<option value=\"foo\">foo</option>\n<option value=\"bar\">bar</option>"
Return value:
"<select name=\"my_name\" id=\"my_name\"><option value="foo">foo</option>\n<option value="bar">bar</option></select>"
At least this reveals what the name parameter is for.
Even weirder, the text is not escaped if you pass the return value directly to select_tag without letting it print on the console:
H.new.select_tag :name, H.new.options_for_select(["foo","bar"])
Return value:
"<select name=\"name\" id=\"name\"><option value=\"foo\">foo</option>\n<option value=\"bar\">bar</option></select>"
WTF is going on here?
In the course of writing this question, I stumbled on its answer: Ruby has been lying to me (like it always does).
When you evaluate:
H.new.options_for_select ["foo","bar"]
Ruby tells you that the result was a String. But that's only because Pry and Irb both silently call .to_s on everything, and the thing that gets returned from options_for_select has a to_s. The truth:
(H.new.options_for_select ["foo","bar"]).class
=> ActiveSupport::SafeBuffer
ActiveSupport::SafeBuffer.new("<foo>")
=> "<foo>"
So whoever wrote these methods assumed that you want to incorporate raw, user-provided strings into your <select> tags, and those strings could contain attempts at HTML/JavaScript injection, so they must be escaped.
ActiveView treats all strings as suspect, but it is possible to mark certain strings as "safe" by wrapping them in an ActiveSupport::SafeBuffer.

Why is this XSS, according to Brakeman?

Can someone explain to me why this is a security problem?
= link_to new_locale.to_s, params.slice(:id, :reader_id, :screen_type).merge(locale: new_locale)
I am trying to add a simple partial to my project to be able to switch between languages. I don't really want this partial to have to interact with each controller or switch the user to a different page or have to know all possible valid parameters.
I did a quick pass over the source and I suspect one of the following is triggering it:
You're calling .to_s for the first argument to link_to, resulting in an html_safe string being passed in.
User input being handed directly to link_to, which I believe would be a false positive.
You can dig in further by checking out the source for the link_to XSS tests in Brakeman yourself.

Is there a list of reserved object names for Rails partials?

If I have a partial named _string.erb and try to render it with something like:
= render partial: "string", object: "Some string i want to show in some manner"
And then try to reference in my partial with the name string it throws the error
undefined local variable or method 'string'
The only thing I can think of is that the object name is reserved. If something else is going on I would love to hear about it.
Just for clarity, everything works fine for a partial with another name. eg in the partial dog rendered with the following code
= render partial: "dog", object: "Some string i want to show in some manner"
I can reference the variable dog without any issues. I am also NOT using #string.
I realize I may be able to find this out by digging into the actual source code (which I intend to do after posting this), but if anyone has an idea what is going I would love to hear it. If I find a solution I will post it.
EDIT - edited to add the exact error being thrown due to questions about it in the comments.
EDIT - I tried to simplify my example when writing this and ultimately ended up proving that string isn't a reserved keyword, and my code was erroring because the value I was passing was nil in the db.
There is no official definitive list of reserved words. The list found at https://reservedwords.herokuapp.com/ is the best I've come accross. String is included in the list, so very well may be the cause of your issue.
I am 99% sure the source of my error was that my string I was passing in was nil. I expected this to return nil to the partial under that variable name string, but that doesn't appear to be the case and I just missed it.

Rails I18n _html suffix rule and translate helper called from a controller

According to ruby docs, the translate (or t) helper delegates to I18n#translate but also performs several additional functions, among which is: "it’ll mark the translation as safe HTML if the key has the suffix _html".
I would expect that it should work equally in both views and in controllers, but in my experience it doesn't: t(:hello_html) does work as expected in views (marks the translation as html_safe), but it does not mark the result as safe html when invoked from a controller.
To reproduce the problem you could add hello_html: '<i>Hello world</i>' to your locales/en.yml and flash.now[:notice] = t(:hello_html) to any convenient action of any controller. For me that resulted in an escaped html markup in a flash messages area which was an unexpected outcome for me.
My questions are:
is there anyone else who experienced or is able to reproduce this problem?
what is it: a rails bug, a feature, or just my project's unique "oddity"?
is there any easy way to work this around?
(Tested in rails 3.2.11 and 3.2.13)
You are correct about this functionality not being available to controllers given that the overloaded .t method is defined in ActionView::Helpers::TranslationHelper. I think this is probably an oversight as opposed to an actual bug.
Off the top of my head there are 2 ways you can get around this in your project :
Call .html_safe in your controller (this worked for me in a quick test).
flash[:notice] = t(:hello_html).html_safe
Send the translation key as the flash message as opposed to the actual message :
Controller :
flash[:translate_notice] = :hello_html
View :
%div= t flash[:translate_notice]
Granted, the latter option might get a bit messy if you need to pass interpolations, YMMV.

Why the "_path" route helper returns string not marked as html_safe?

The "_path" route helper returns string not marked as html_safe.
I don't know for sure - maybe it's indeed not html safe, but when I pass something like "foo>bar" to _path helper it generates string like:
/aa/foo%3Ebar/bb
Which looks safe.
However, html_safe? for that string is false and if I pass it to template, expectedly I've got:
/aa/foo%3Ebar/bb
Which looks not so nice.
I can call .html_safe on helper output, but maybe there are some cases when _path helpers emit unsafe characters?
Anyway, I don't like the idea to call html_safe on every helper output, and hope that framework take care of that stuff.
Any thought?
This is quit usefull becaus the client may pass variables to the url and if the path would be marked as html_safe for deafult he could simply write some javascript/html/... to the url and it would be executed. That is called a Cross Site Scripting and one of the most "popular" security holes. Of cause its "only" a client side attack but it might get dangerous for your users so its better to not change this by default!

Resources