I'm looking to style a flash notice within a helper passing along an array. So something like:
def import
#fruit = Fruit::Import.run(params[:food_id], params[:file]).result
if #fruit.empty?
flash[:notice] = 'Success'
else
flash_message(#fruit)
end
end
I made sure to include in the controller include FoodsHelper at the top of the controller.
So within the helper I have:
def flash_message(fruit)
content_tag(:ul, class: 'alert alert-error') do
fruit.each do |type, msg|
msg.each do |item|
content_tag(:li, item, class: "flash_#{type}")
end
end
end
end
The hope would have a ul and each of the elements within the array from fruit would display as a list item. This however comes up with undefined method `content_tag' did you mean content_type?
Is there a good way to iterate a flash notice with content_tag?
You could use some code from this (I don't really know what you are trying to do here)
The hope would have a ul and each of the elements within the array
from fruit would display as a list item. This however comes up with
undefined method `content_tag' did you mean content_type?
If you want to use content_tag from a controller you need to add this:
include ActionView::Helpers::TagHelper
or in Rails 5 just use helpers.content_tag
helpers.content_tag(:ul, class: 'alert alert-error') do ...
Is there a good way to iterate a flash notice with content_tag?
There's no such a thing as 'iterate a flash[:notice] with content_tag'
Maybe you want to do this:
Controller:
def import
#fruit = Fruit::Import.run(params[:food_id], params[:file]).result
if #fruit.empty?
flash[:notice] = 'Success'
else
flash[:notice] = #fruit
end
end
Helper:
def flash_message
content_tag(:ul, class: 'alert alert-error') do
flash.each do |type, msg|
if msg.is_a? Array
msg.each do |item|
content_tag(:li, item, class: "flash_#{type}")
end
else
content_tag(:li, msg, class: "flash_#{type}")
end
end
end
end
View:
<%= flash_message %>
Related
I've got a presenter which I would like to make the each_with_index method available in. I've added include Enumerable in my base presenter however, I'm still getting a no method error. My current code is below:
index.erb
<% #bids.each_with_index do |bid, index| %>
<% present bid do |bid_presenter| %>
<div class="large-4 medium-4 columns <%= bid_presenter.last_column %>"></div>
<% end %>
<% end %>
bid_presenter.rb
class BidPresenter < BasePresenter
presents :bid
def last_column
if index == bid.size - 1
'end'
end
end
end
base_presenter.rb
class BasePresenter
include Enumerable
def initialize(object, template)
#object = object
#template = template
end
private
def self.presents(name)
define_method(name) do
#object
end
end
# h method returns the template object
def h
#template
end
# if h is missing fallback to template
def method_missing(*args, &block)
#template.send(*args, &block)
end
end
bids_controller.erb
# GET /bids
# GET /bids.json
def index
#bids = current_user.bids
end
You are forwarding all not explicitly implemented methods to #template. Whatever #template is doesn't seem to properly implement each. You need to make #template respond properly to each.
I'm new on rails and I have a book to study them. In one practice, I created a helper in my Application Helper, the test from RSpec work fine, until I have to print the result of my helper. No show any result and no error happens.
application_helper.rb
module ApplicationHelper
def title(*parts)
unless parts.empty?
content_for :title do
(parts << "Ticketee").join(" - ")
end
end
end
end
show.html.erb
<% title(#project.name) %>
projects_controller.rb
class ProjectsController < ApplicationController
def show
#project = Project.find(params[:id])
end
end
and when I go to the show link I supposed to see "Random Project name - Ticketee", however only they show me "Ticketee".
Any help...
<% title(#project.name) %>
Means don't show to the user
<%= title(#project.name) %>
Means show to the user - notice the equals.
In my Rails app I already have the following code:
<% %w(number_of_students edit_class_name tech_help).each do |modal| %>
<%= render "common/modals/#{modal}" %>
<% end %>
There will be a few more modals added into app/views/common/modals and instead of explicitly listing them out in the %w() I was wanting to loop through the common/modals directory and just render each file.
Here is what I came up with:
def render_modals
files = Dir.glob("#{Rails.root}/app/views/common/modals/*").collect { |file| File.basename(file, ".html.erb").sub("_", "") }.flatten
files.collect do |modal|
render partial: "common/modals/#{modal}"
end.join.html_safe
end
define a simple method in where is more appropriate (maybe app helper?) like this:
def modals
%w(number_of_students edit_class_name tech_help)
end
if you need these modals in a controller/model too, maybe you should define this method in an appropriate class? For example
class Modal
def self.types
%w(number_of_students edit_class_name tech_help)
end
end
Also, if you are rendering the templates often, then also define
def render_modals
modals.map do |modal| # Modals here should be the method that you just defined, example, Modal.types
render partial: "common/modals/#{modal}"
end.join
end
I am making a view helper to render set of data in a format. I made these classes
require 'app/data_list/helper'
module App
module DataList
autoload :Builder, 'app/data_list/builder'
##data_list_tag = :ol
##list_tag = :ul
end
end
ActionView::Base.send :include, App::DataList::Helper
helper is
module App
module DataList
module Helper
def data_list_for(object, html_options={}, &block)
builder = App::DataList::Builder
arr_content = []
object.each do |o|
arr_content << capture(builder.new(o, self), &block)
end
content_tag(:ol, arr_content.join(" ").html_safe, html_options).html_safe
end
end
end
end
builder is
require 'app/data_list/column'
module App
module DataList
class Builder
include App::DataList::Column
include ActionView::Helpers::TagHelper
include ActionView::Helpers::AssetTagHelper
attr_reader :object, :template
def initialize(object, template)
#object, #template = object, template
end
protected
def wrap_list_item(name, value, options, &block)
content_tag(:li, value).html_safe
end
end
end
end
column module is
module App
module DataList
module Column
def column(attribute_name, options={}, &block)
collection_block, block = block, nil if block_given?
puts attribute_name
value = if block
block
elsif #object.respond_to?(:"human_#{attribute_name}")
#object.send :"human_#{attribute_name}"
else
#object.send(attribute_name)
end
wrap_list_item(attribute_name, value, options, &collection_block)
end
end
end
end
Now i write code to test it
<%= data_list_for #contracts do |l| %>
<%= l.column :age %>
<%= l.column :contact do |c| %>
<%= c.column :phones %>
<% end %>
<%= l.column :company %>
<% end %>
Every thing is working fine , age , contact , company is working fine. But phones for the contact is not showing.
Does any one have an idea, i know i have missed something in the code. Looking for your help.
Updated question with complete source is enter link description here
There are two issues I can see in the column module.
1) If a block is provided you're setting it to nil - so if block is always returning false. 2) Even if block wasn't nil you're just returning the block as the value, not actually passing control to the block. You should be calling block.call or yielding. Implicit blocks execute faster, so I think your column module should look more like this:
module DataList
module Column
def column(attribute_name, options={})
value = begin
if block_given?
yield self.class.new(#object.send(attribute_name), #template)
elsif #object.respond_to?(:"human_#{attribute_name}")
#object.send :"human_#{attribute_name}"
else
#object.send(attribute_name)
end
end
wrap_list_item(attribute_name, value, options)
end
end
end
The solution is now posted in the discussion.
I want to make a helper like the following.
def my_div some_options, &block
# How do I print the result of the block?
end
You should use CaptureHelper.
def my_div(some_options, &block)
# capture the value of the block a string
content = capture(&block)
# concat the value to the output
concat(content)
end
<% my_div([]) do %>
<p>The content</p>
<% end %>
def my_div(some_options, &block)
# capture the value of the block a string
# and returns it. You MUST use <%= in your view.
capture(&block)
end
<%= my_div([]) do %>
<p>The content</p>
<% end %>
Use capture + concat if you need to concat the output.
Use capture if you need to capture and then reuse the content. If your block doesn't explicitely use <%=, then you MUST call concat (preferred way).
This is an example of a method that hides the content if the user it not an admin.
def if_admin(options = {}, &block)
if admin?
concat content_tag(:div, capture(&block), options)
end
end
<% if_admin(:style => "admin") do %>
<p>Super secret content.</p>
<% end %>
so two things that are important:
rails ignores anything that isn't a string in a content_tag (and content_for)
you can't use Array#join (etc.) because it produces unsafe strings, you need to use safe_join and content_tag to have safe strings
I didn't need either capture or concat in my case.
def map_join(objects, &block)
safe_join(objects.map(&block))
end
def list(objects, &block)
if objects.none?
content_tag(:p, "none")
else
content_tag(:ul, class: "disc") do
map_join(objects) do |object|
content_tag(:li) do
block.call(object)
end
end
end
end
end
this can be used like this:
= list(#users) do |user|
=> render user
= link_to "show", user
(this is slim but works fine with erb too)
http://www.rubycentral.com/book/tut_containers.html
The yield statement will return the result of the block passed. So if you wanted to print (console?)
def my_div &block
yield
end
my_div { puts "Something" }
Would output "Something"
But:
What is the idea of your method? Outputting a DIV?