如何在 rails 中将两个属性作为text_method传递给 collection_select

How to pass two attributes as the text_method to a collection_select in rails

提问人:Lee McAlilly 提问时间:7/29/2021 更新时间:7/30/2021 访问量:171

问:

我有一个 in a rails 表单,如下所示:collection_select

<%= form.collection_select :post_id, Post.all, :id, :title, {}, { class: "mt-1 block" } %>

我似乎无法从文档或谷歌搜索中弄清楚如何将多个属性从 Post 传递到下拉列表,以便用户看到的不仅仅是 .像这样的东西::title

<%= form.collection_select :post_id, Post.all, :id, :title + :category, {}, { class: "mt-1 block" } %>

我可以创建一个自定义方法以在模型中传递给 like,例如:text_method:title_with_categoryPost

<%= form.collection_select :post_id, Post.all, :id, :title_with_category, {}, { class: "mt-1 block" } %>

Post.rb:

def title_with_category
  self.title + " " + self.category
end

但这是最好的方法吗?如果是这样,定义这一点的合适位置是什么?模型?或者这应该在帮手中?如果它是帮助程序,它应该在应用程序帮助程序中吗?

Ruby-on-Rails Ruby 表单 集合-选择

评论


答:

0赞 TomDunning 7/29/2021 #1

首先,这样做更安全,以防其中一个项目为零:

邮政.rb

def title_with_category
  "#{title} #{category}"
end

接下来您的选择。在控制器中,将选项作为属性返回:

def new
  @post_options = Post.all.collect{|post| [post.id, post.title_and_category]}
  # OR
  @post_options = Post.all.collect{|post| [post.id, "#{post.title} #{post.category}"]}
  # you can skip the model method with the second option
end

在表格上:

<%= form.select :post_id, @post_options, {}, { class: "mt-1 block" } %>

请参阅表单选择

评论

0赞 max 7/29/2021
这个答案中唯一有意义的部分是使用插值而不是串联。手动创建选项的整个步骤是完全多余的。
0赞 Lee McAlilly 7/30/2021
汤姆的好点。感谢您指出这一点。我想我更愿意在模型中执行此操作,而不是将 post 选项收集到实例变量中,但感谢您对此的看法。#{post.title} #{post.category}
0赞 max 7/29/2021 #2

您可以为 和 参数传递可调用对象:collection_selectvalue_methodtext_method

<%= form.collection_select :post_id,
                           Post.all,
                           :id, # value_method
                           ->(p){ "#{p.title} #{p.category}" }, # text_method
                           {},
                           { class: "mt-1 block" }
%>

可调用对象是响应该方法的任何对象,例如 lamdba 和 proc 对象。call

在循环的每次迭代中,它都会随 post 一起调用。

定义这一点的合适位置是什么?模型?或者这应该在帮手中?如果它是帮助程序,它应该在应用程序帮助程序中吗?

如果您选择将其提取到单独的方法中,则没有明确的答案。该模型将是最简单的解决方案,但你也可以争辩说,表示逻辑应该与业务逻辑分开,并且模型已经具有大量的责任。

我想我们都同意 ApplicationHelper 是最不合适的选择,除非你只是想把你的代码扔进垃圾抽屉里。

此代码可以进入 Post、PostHelper、PostPresenter(如果您喜欢装饰器模式)或自定义表单构建器(这似乎有点矫枉过正)。

评论

0赞 Lee McAlilly 7/30/2021
谢谢 Max. 没想过使用这样的 lambda 来循环。这是我所问问题的要点,但我认为现在我将坚持将其定义为模型中的方法。在我看来,这似乎比视图中有那么多逻辑更清晰。但真的很欣赏你对这个问题的看法。