Reputation: 9316
I have a collection_select
in a rails form that looks like this:
<%= form.collection_select :post_id, Post.all, :id, :title, {}, { class: "mt-1 block" } %>
What I can't seem to figure out from the docs or googling, is how to pass multiple attributes from the Post to the dropdown so the user sees more than just the :title
. Something like this:
<%= form.collection_select :post_id, Post.all, :id, :title + :category, {}, { class: "mt-1 block" } %>
I can create a custom method to pass to text_method
like :title_with_category
in the Post
model like:
<%= 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
But is this the best way to do this? If so, what is the appropriate place to define this? The model? Or should this be in a helper? If it's a helper, should it be in the application helper?
Upvotes: 0
Views: 239
Reputation: 101811
You can pass a callable to collection_select
for both the value_method
and text_method
arguments:
<%= form.collection_select :post_id,
Post.all,
:id, # value_method
->(p){ "#{p.title} #{p.category}" }, # text_method
{},
{ class: "mt-1 block" }
%>
A callable is any object that responds to the call
method such as lamdba and proc objects.
It is called with the post for each iteration of the loop.
What is the appropriate place to define this? The model? Or should this be in a helper? If it's a helper, should it be in the application helper?
There is no clear cut answer if you choose to extract this out into a separate method. The model would be the simplest solution but you can also argue that presentational logic should be separated from buisness logic and that models already have tons of responsiblities.
I think we can all agree on that ApplicationHelper is the least suitible option unless you to just are aiming to toss your code into a junk drawer.
This code could go into Post, PostHelper, PostPresenter (if you're into the decorator pattern) or a custom form builder (which seems slightly overkill).
Upvotes: 0
Reputation: 4877
Firstly, it's safer to do this in case one of the items is ever nil:
Post.rb
def title_with_category
"#{title} #{category}"
end
Next your selection. In the controller, return the options as an attribute:
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
And on the form:
<%= form.select :post_id, @post_options, {}, { class: "mt-1 block" } %>
See form select.
Upvotes: 0