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

Posted

技术标签:

【中文标题】如何将两个属性作为 text_method 传递给 rails 中的 collection_select【英文标题】:How to pass two attributes as the text_method to a collection_select in rails 【发布时间】:2021-10-04 13:17:36 【问题描述】:

我有一个collection_select,它的rails 形式如下所示:

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

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

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

我可以创建一个自定义方法传递给text_method,例如Post 模型中的:title_with_category,例如:

<%= 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

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

【问题讨论】:

【参考方案1】:

首先,如果其中一项为 nil,这样做会更安全:

Post.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"  %>

见form select。

【讨论】:

这个答案中唯一有意义的部分是使用插值而不是串联。手动创建选项的整个步骤是完全多余的。 #post.title #post.category Tom 的好点子。感谢您指出了这一点。我认为我更愿意在模型中执行此操作,而不是将发布选项收集到实例变量中,但感谢您对此的看法。【参考方案2】:

您可以为value_methodtext_method 参数传递一个可调用的collection_select

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

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

循环的每次迭代都会在帖子中调用它。

定义这个的合适的地方是什么?该模型?还是应该在助手中?如果是助手,应该在应用助手中吗?

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

我认为我们都同意 ApplicationHelper 是最不合适的选择,除非您只是打算将代码扔进垃圾抽屉。

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

【讨论】:

谢谢马克斯。没有考虑过使用这样的 lambda 循环。这是我所问问题的要点,但我认为现在我将坚持将其定义为模型中的一种方法。这对我来说似乎比在视图中有那么多逻辑更清晰。但非常感谢您对这个问题的看法。

以上是关于如何将两个属性作为 text_method 传递给 rails 中的 collection_select的主要内容,如果未能解决你的问题,请参考以下文章

如何将对象(或关联数组)作为属性值传递给我的 Web 组件

如何将本地 Maven m2 作为属性传递给 Gradle?

如何将反应组件作为变量传递给子组件?

我如何将两个数据框列值作为键传递给2键到一个值字典,然后将结果传递到另一列?

如何将系统属性传递给 jar 文件

如何通过控制器将两个不同模型的值作为 Laravel 8 中的单个返回变量传递给视图文件