Rails: Print to page, not to console? - ruby-on-rails

I want to write a helper method to print a list of radio buttons. The obvious way to do it is to have the helper method return a string of html code for my view file to render.
But that's just not pretty, appending <li> after <li> to a string, then returning it.
The code would be more readable, of course, if I could just print each line of html in turn. Can I print lines to an output stream and have it end up on my page (not on the server console)?
(I'm using rails 2.3.5, btw.)

You can build up a list in a helper method by calling content_tag and passing in the desired element and a block that renders some HTML (like the radio_button helper), then joining the whole mess into a string, e.g. (air code):
module SomeHelper
def radio_button_list(things)
things.collect do |thing|
content_tag(:li) { radio_button(thing.foo, thing.bar, thing.baz) }
end.join
end
end

Related

How can I re-use blocks of haml with arguments?

I've been using HAML for over 10 years, and this simple use case continues to elude me.
Say I have the following haml code
- links.each do |link|
= link_to link.url do
%i.fa.fa-map
= link.text
This block works while looping only, but imagine a situation where I want to reuse the block in multiple loops, or in multiple places in the HAML file. I do not currently know how to do that without creating a separate partial or helper. When the block is big enough, I often will create a partial, but often the block is small and a partial seems tedious overkill. Sometimes I have several blocks like this that I only want re-used in one HAML file.
I tried first to create this with content_for but it doesn't accept arguments and can't be cached.
My second attempt was with capture_haml, but I think that has to be called directly indide of HAML, not a ruby method. The following obviously fails for syntax reasons, but you see what I'm trying to do:
:ruby
def entry_link(url, text)
capture_haml(url, text) do |url, text|
= link_to url do
%i.fa.fa-map
text
end
end
Update:
I was able to get this far, which is functional but ugly AF.
:ruby
def entry_link(url, text)
capture_haml(url, text) do |url, text|
link_to url do
haml_tag :i, {class: 'fa fa-map'}
haml_concat(text)
end
end
end
= entry_link('/', 'My Link')
The following would be a more acceptable syntax, but I get the strange error undefined local variable or method _hamlout'`
- def entry_link(url, text)
- link_to url do
%i.fa.fa-map
text

Create html tag wrapper in Rails application

I'm new to Rails and I'd like to create a helper function that consume whatever I pass and returns wrapped element. I was trying to use something like content_tag / tag however it won't cover all of my use cases. It should create div and wrap it over element that I pass as an argument. In most cases it would be just nested HTML. I'm looking for something like code below that would consume anything, it would be nice if it would work with render method as well.
Helper method:
def helper_method(content)
content_tag(:div, content)
end
in ERB file:
helper_method('<span><p>Something</p></span>')
In React I would just pass "children". How should I handle that in Rails?
Capture the block, and pass it to content_tag like so:
def something(css_class, &block)
content_tag(:div, class: css_class, &block)
end
Use it in a view like so:
<%= something('my-css-class') do %>
...your content here...
<% end %>
This avoids the security issues inherent with .html_safe.
You'll use exactly how you described it. You can return HTML safe strings from helpers by setting the string as html_safe
Example:
def helper_method content
content_tag(:div, content.html_safe)
end
Note that, this can potentially introduce security issues. You don't want to call html_safe on user entered strings because scripts will execute. It's not really safe as the name suggests ;)
Read more:
stay-safe-while-using-html-safe-in-rails-9e368836fac1
everything-you-know-about-html_safe-is-wrong
proper use of html_safe
For ideal approach, use sanitize:
def helper_method content
content_tag(:div, sanitize(content))
end

What is the syntax for named yield with both names and parameters in ruby/rails?

One could use yield with a :name in views in rails:
= yield :some_place
so then using then using content_for :some_place do ... to insert a code block only in there where yield :some_place is placed (http://guides.rubyonrails.org/layouts_and_rendering.html#using-the-content-for-method).
Also ruby allows passing parameters in the yiled (http://www.tutorialspoint.com/ruby/ruby_blocks.htm):
def test
yield 5
puts "You are in the method test"
yield 100
end
test {|i| puts "You are in the block #{i}"}
But I didn't find anything about using yield/content_for both with names and parameters in rails views:
= yield :some_place, 5, 6
...
= content_for :some_place do |a,b|
h3 = "Yield provided parameters: #{a} and #{b}"
Is it possible? Where is the official rails or ruby syntax for yield statements and passing blocks?
I heard something about the Proc.new() that could be somehow related to the problem.
content_for(:name) evaluates first, and stores a snip of HTML for later use. yield(:name) only fetches this content. Hence, you can't pass arguments into a method that was already called, and won't be called again.
You probably merely need to cut a partial HTML.erb file, and render it from your target location. Render takes named parameters as a hash.

Helper method with the same name as partial

I have a helper with a method named search_form like this:
module Admin::BaseHelper
def search_form(*args)
# my great code here
end
end
To call this method in my HAML code, I can do this:
= search_form
= search_form()
= search_form(param1: "value1", param2: "value2"...)
My problem is with this first call. When I do this in any HAML file, it renders my helper. Except if my file name is _search_form.html.haml. Is that case, it returns nil.
If I put a raise error in the helper, I notice that my method isn't being called, but I am not able to find what is being called and why.
If I use the syntax on the second and third lines, it works as expected by calling my helper method.
So my question is: is this standard Rails behavior or a bug?
By default, Rails will look for a local variable with the same name as your partial, which may conflict with existing method names.
One way to get around this is to simply redefine the method inside your partial:
<% search_form = self.search_form %>
# Rest of the partial's code

Is it possible to have Haml indent HTML generated by a view helper in Rails?

Say I have a things resource with a view helper method such as:
module ThingsHelper
def foo
ret = ""
3.times { ret += content_tag(:li, "foo") }
content_tag(:ul, ret)
end
end
This, then, is used in a template:
%p
= foo
The HTML source that's generated looks like this:
<!DOCTYPE html>
<html>
<head>
<title>Foo</title>
</head>
</html>
<body>
<p>
<ul><li>foo</li><li>foo</li><li>foo</li></ul>
</p>
</body>
As you can see, the helper output is not indented as the rest of the code. Any way to remedy this?
Try out the haml_tag helper method provided with Haml. It's like content_tag in some ways, but it outputs properly indented HTML. The main difference is that it outputs directly to the template, rather than returning a string. For example:
module ThingsHelper
def foo
haml_tag :ul do
3.times { haml_tag(:li, "foo") }
end
end
end
(As a side note, it's considered very bad Ruby style to use something other than two spaces for indentation).
I doubt it - at least not without a significant amount of mucking around.
Your = foo is simply printing what is returned by your foo helper - it's not getting parsed by haml. And you can't write haml in your helper method either.
The simplest way I can think of to deal with this is to just add literal whitespace characters in your helper (ie \n and \t).
You could also require the relevant haml class(es) in your helper and call the parsing methods manually on ret, but this is probably more complicated than worthwhile.

Resources