我有一个看起来像这样的帮手:
override func viewDidLoad() {
super.viewDidLoad()
let button = UIButton(frame: CGRect(x: 0, y: 0, width: 80, height: 30))
button.hidden = true
button.backgroundColor = UIColor.redColor()
self.navigationItem.rightBarButtonItem = UIBarButtonItem(customView: button)
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
let view = self.navigationItem.rightBarButtonItem?.customView
view?.hidden = false
view?.alpha = 0
UIView.animateWithDuration(0.4, animations: { () -> Void in
view?.alpha = 1.0
})
}
我需要渲染所有链接及其嵌套的if current_user.find_voted_items(vote_scope: :inspired).include?(post)
link_to vote_inspired_post_path(post, vote_scope: :inspired), method: :post, data: { confirm: 'Are you sure this post Inspires you?' }, class: "btn btn-default" do
"<i class='fa fa-lightbulb-o'></i> <br />Inspired".html_safe
end
link_to vote_happy_post_path(post, vote_scope: :happy), method: :post, data: { confirm: 'Are you sure this post makes you happy?' }, class: "btn btn-success" do
"<i class='fa fa-smile-o'></i> <br />Happy".html_safe
end
link_to vote_disappointed_post_path(post, vote_scope: :disappointed), method: :post, data: { confirm: 'Are you sure this post disappointed you?' }, class: "btn btn-info" do
"<i class='fa fa-meh-o'></i> <br />Disappointed".html_safe
end
link_to vote_upset_post_path(post, vote_scope: :upset), method: :post, data: { confirm: 'Are you sure this post upsets you?' }, class: "btn btn-inverse" do
"<i class='fa fa-frown-o'></i> <br />Upset".html_safe
end
end
标记 - 但由于某种原因,此版本只是渲染最后一行。
所有这些都在名为<i>
的方法中,在视图中就像这样调用:show_vote_buttons(post)
解决这个问题的最佳方法是什么?
答案 0 :(得分:5)
基本上,这背后的原因是<%= %>
呈现show_vote_buttons
方法的输出。此方法没有显式返回任何内容,因此在您的情况下,返回最后一个计算的表达式,即最后link_to
个输出。
在一般情况下,如果您没有使用辅助方法并且仅使用多个link_to
调用粘贴它的正文,您将获得相同的行为。原因类似:<%= %>
不呈现每个link_to
,它在<%= %>
内执行代码,然后输出最后一次计算表达式的结果。
我看到两种不同的方法来改变输出:
<<
周围使用()
和括号link_to
; "
的字符串,并在其中插入link_to
个#{}
输出; concat
; <%= %>
输出每个link_to
。 P.S。在测试了所有四种方法之后,我得出结论(这是个人意见),第二种方法更为可取,至少因为它在视图中保持渲染并避免可能看起来混乱的连接。例如,在Devise gem中使用了类似的方法,其中所有共享链接都位于app/views/devise/shared/_links.html.erb
部分。
答案 1 :(得分:1)
但由于某种原因,这个版本只是渲染最后一行。
这是因为在Ruby中,如果方法没有显式return
,则方法的返回值是在方法退出之前执行的最后一行的值。如果您想从方法中返回多个值,请使用return
关键字并使用逗号分隔您的值。
#will return an array [1,2,3]
def some_method
return 1,2,3
end
此外,我同意其他答案,即您的代码应该更干,但我只是想澄清您的原始问题。
答案 2 :(得分:0)
@suslov围绕这个答案完美地解释了这个原因。元编程可能会使代码保持DRY:
DATA = {
inspired: { ico: 'fa-lightbulb-o',
msg: 'Are you sure this post Inspires you?',
btn: 'btn-default' },
happy: { ico: 'fa-smile-o',
msg: 'Are you sure this post makes you happy?',
btn: 'btn-success' },
... }
if current_user.find_voted_items(vote_scope: :inspired).include?(post)
DATA.map do |k, v|
instance_eval %Q{
link_to vote_#{k}_post_path(post, vote_scope: :#{k}),
method: :post,
data: { confirm: #{v[:msg]} },
class: "btn #{v[:btn]}" do
"<i class='fa #{v[:ico]'></i> <br />#{k.capitalize}".html_safe
end
}.join($/) # return them all, concatenated with separator
end
end
答案 3 :(得分:0)
尝试使用此代码
if current_user.find_voted_items(vote_scope: :inspired).include?(post)
concat(link_to vote_inspired_post_path(post, vote_scope: :inspired), method: :post, data: { confirm: 'Are you sure this post Inspires you?' }, class: "btn btn-default" do
safe_concat(content_tag(:i, "Inspired", calss: "fa fa-lightbulb-o"))
end)
concat(link_to vote_happy_post_path(post, vote_scope: :happy), method: :post, data: { confirm: 'Are you sure this post makes you happy?' }, class: "btn btn-success" do
safe_concat(content_tag(:i, "Happy", calss: "fa fa-smile-o"))
end)
concat(link_to vote_disappointed_post_path(post, vote_scope: :disappointed), method: :post, data: { confirm: 'Are you sure this post disappointed you?' }, class: "btn btn-info" do
safe_concat(content_tag(:i, "Disappointed", calss: "fa fa-meh-o"))
end)
concat(link_to vote_upset_post_path(post, vote_scope: :upset), method: :post, data: { confirm: 'Are you sure this post upsets you?' }, class: "btn btn-inverse" do
safe_concat(content_tag(:i, "Upset", calss: "fa fa-frown-o"))
end)
end
注意: 未经过测试。