How do I generate a bunch of checkboxes from a collection? - ruby-on-rails

I have two models User and Category that have a HABTM association.
I would like to generate checkboxes from a collection of Category items on my view, and have them associated with the current_user.
How do I do that?
Thanks.
P.S. I know that I can do the equivalent for a dropdown menu with options_from_collection_for_select. I also know that Rails has a checkbox_tag helper. But not quite sure how to do both of them. I know I can just do it manually with an each loop or something, but am wondering if there is something native to Rails 3 that I am missing.

Did you check out formtastic or simple_form
They have helpers to write your forms more easily, also to handle simple associations.
E.g. in simple_form you can just write
= simple_form_for #user do
= f.association :categories, :as => :check_boxes
In form_tastic you would write
= simple_form_for #user do
= f.input :categories, :as => :check_boxes
Hope this helps.

You can use a collection_select and feed it the options. Assuming you have a form builder wrapped around a user instance, you can do something like this:
form_for current_user do |f|
f.collection_select(
:category_ids, # the param key, so params[:user][:category_ids]
f.object.categories, # the collection of items in the list
:id, # option value
:name # option string
)
end
You may want to pass the :multiple => true option on the end if needed.

Related

Formtastic pre-check few checkboxes

I'm trying to manually tell formtastic to check a few checkboxes. #some_array currently has an element called checked which exists for each member.
= f.input :cboxes, label: "CBoxes", as: :check_boxes,
collection: #some_array.map { |a| [a[:name], a[:id]] }
I've tried to set the input_html to { checked: 'checked' } (How to pre-check checkboxes in formtastic) but this checks all checkboxes, not just the select few that I want.
The contents of #some_array are coming via an API, and I can't change the database structure (Ruby on Rails + Formtastic: Not checking checkboxes for multiple checked answers)
Suggestions?
If you are editing an ActiveModel, you don't need to "manually select checkboxes".
Let's consider a simple example with a single User model which has fields username and roles. Roles field is a string column, which Rails serializes as an Array. It might also be has_many relation to other ActiveModel, but we assume it's an Array for simplicity.
User is defined in user.rb:
class User < ActiveRecord::Base
serialize :roles, Array
end
Now you can "assign manually" desired roles to User in your controller:
#user = User.new(username: 'dimakura', roles: ['admin', 'editor'])
and define form in your view:
<%= semantic_form_for #user do |f| %>
<%= f.input :username %>
<%= f.input :roles, as: :check_boxes, collection: ['owner', 'admin', 'editor', 'viewer'] %>
<% end %>
In given example only "admin" and "editor" roles will be pre-selected in form. The "owner" and "viewer" role won't be selected.
Update Official documentation states:
Formtastic, much like Rails, is very ActiveRecord-centric.
But actually it's not a big challenge to create ActiveRecord-compatible model yourself. An example of doing this can be found in this blog post.

simple_form association field not pre-selecting selected elements

I have a Message data model in Rails with a "virtual" association. That is, a method that returns a collection of "associated objects", but it is not an actual association in the ActiveRecord sense.
class Message
def recipients
#recipients
end
def recipients=(arr)
#recipients = arr
end
end
The thing with simple_form is that, when I try to show a association field, it fails because there's no :recipients association:
= simple_form_for(#message) do |f|
= f.association :recipients, collection: Recipient.all
The solution seemed then simple, I went on to use a f.input with the as: :select option:
= simple_form_for(#message) do |f|
= f.input :recipients, as: :select, collection: Recipient.all
And this works fine, except for the fact that it does not automatically detect the values already in #message.recipients so that the elements appear pre-selected when the form is rendered.
If Message#recipients were an actual association, in the ActiveRecord sense, then f.association in the form would do this as well. But for reasons that go beyond the scope of this question, I can't make it as an actual association.
The question then is, can I achieve f.input :recipients, as: :select to pre-select the selected elements?
Well, this is embarrassing. Just after posting this, I came up with an idea that ended up solving the problem:
class Message
# ...
def recipient_ids
# ...
end
def recipient_ids=(arr)
# ...
end
end
I added the recipient_ids getter and setter, in addition to the association getter and setter that I had before.
Then I updated the form input field to refer to :recipient_ids instead of :recipients:
= simple_form_for(#message) do |f|
= f.input :recipient_ids, as: :select, collection: Recipient.all

semantic_field_for for arbitrary attribute

I am quit new to rails. I have been using formtastic in my project and I find it quite easy to deal with the form objects. I have a small problem which I hope to clear out here.
I want to create a form for arbitrary objects and a has_many type of nested form for it. What I mean is semantic_form_for does not use any model instead uses symbol for creating form and this form now has to have a to_many type of semantic_fields_for. This is how my code looks,
= semantic_form_for :company do |f|
= f.inputs "company" do
= f.input :name
= f.input :enterprise_code
= f.semantic_fields_for :email do |e|
= f.inputs "email" do
= f.input :address
The form above is not associated to any model. I will pick these attributes in the controller and assign it individually. The email fields in the form has to be like has_many. Now, it is like one to one. How can this be achieved.
I used formtastic only once so i might be wrong but i don't think there's anything mentioned that you can use it only for one type of association. It only says that you for nested forms we can use semantic_fields_for :model and then both model's must be setup correctly with accepts_nested_attributes_for

Manipulating tags with acts_as_taggable_on and ActiveAdmin

I have a Post model which I'm accessing through ActiveAdmin. It's also taggable using the acts_as_taggable_on gem. So the admin can add, edit or delete tags from a specific Post.
The normal way to add the tagging functionality for the resource in your admin panel is by doing this in admin/posts.rb:
ActiveAdmin.register Post do
form do |f|
f.inputs "Details", :multipart => true do
f.input :tag_list
# and the other irrelevant fields goes here
end
f.buttons
end
end
However, I want to have the tags selected from a multiple select form field and not being entered manually in a text field (like it is with the code above). So I've tried doing this:
f.input :tag_list, :as => :select,
:multiple => :true,
:collection => ActsAsTaggableOn::Tag.all
but it doesn't work as expected. This actually creates new tags with some integer values for names and assigns them to that Post. Someone told me that extra code is needed for this to work.
Any clues on how this is done? Here's my model just in case: http://pastie.org/3911123
Thanks in advance.
Instead of
:collection => ActsAsTaggableOn::Tag.all
try
:collection => ActsAsTaggableOn::Tag.pluck(:name)
Setting the collection to Tag.all is going to tag your posts with the tag's ID, since that's how tags are identified by default (that's where the integer values for names are coming from). map(&:name) tells the form builder to use the tag's name instead.

simple_form input with multiple fields

I'm not quite sure what the correct terms are, but what I'm trying to do is in a form (preferably using the simple_form gem) have one of the inputs, :maximum, use both a text field and select box. The user would type in the text box a number, and then select from a dropdown box of hours, days, or months. So 21 days, 3 months, 3 hours, etc. When the form was submitted I would convert that to days and store it in the database. I know how to change the input type in simple_form, but is it possible to have two inputs for one variable?
Sure :) Here is my idea:
First, you define accessors in your user model:
attr_accessor :thing, :another_thing, :and_another_thing
Then in your view, 'inside' form_for helper, you could write for example:
<%= form.input :thing, :as => :boolean %>
<%= form.input :another_thing, :as => :text %>
...or whatever you want. (Note: I am using formtastic here. You should consider using Rails methods if you're not using formtastic gem. )
Finally, you define a callback in you user model:
before_create :build_my_fancy_record
def build_my_fancy_record
self.storage_field = "#{thing} #{another_thing}"
end

Resources