read
Mongoid document supports array
field. Mongoid array field is a ruby array
but it becomes quite complex to manage array field in rails forms.
I didn’t find anything matching on google as well on stackoverflow hence decided to dig into rails form helpers (form_for
, fields_for
).
Finally i am pleased to get it working as expected :)
In below example, product
can have multiple categories
:
<div class='code-highlight'><pre class='code-highlight-pre'><div data-line='1' class='code-highlight-row numbered'><div class='code-highlight-line'>class Product
</div></div><div data-line='2' class='code-highlight-row numbered'><div class='code-highlight-line'> CATEGORIES = %w(Apparel Media Software Sports Agri Education)
</div></div><div data-line='3' class='code-highlight-row numbered'><div class='code-highlight-line'> include Mongoid::Document
</div></div><div data-line='4' class='code-highlight-row numbered'><div class='code-highlight-line'> field :name, :type => String
</div></div><div data-line='5' class='code-highlight-row numbered'><div class='code-highlight-line'> field :categories, :type => Array
</div></div><div data-line='6' class='code-highlight-row numbered'><div class='code-highlight-line'>end</div></div></pre></div>
Here is form code
<div class='code-highlight'><pre class='code-highlight-pre'><div data-line='1' class='code-highlight-row numbered'><div class='code-highlight-line'>= form_for(@product) do |f|
</div></div><div data-line='2' class='code-highlight-row numbered'><div class='code-highlight-line'> = f.text_field :name
</div></div><div data-line='3' class='code-highlight-row numbered'><div class='code-highlight-line'> - Product::CATEGORIES.each do |category|
</div></div><div data-line='4' class='code-highlight-row numbered'><div class='code-highlight-line'> = f.check_box :categories, :name => "product[categories][]", category</div></div></pre></div>
Here is products controller code
<div class='code-highlight'><pre class='code-highlight-pre'><div data-line='1' class='code-highlight-row numbered'><div class='code-highlight-line'>class ProductsController < ApplicationController
</div></div><div data-line='2' class='code-highlight-row numbered'><div class='code-highlight-line'> before_filter :load_product, :only => [:new, :create]
</div></div><div data-line='3' class='code-highlight-row numbered'><div class='code-highlight-line'> </div></div><div data-line='4' class='code-highlight-row numbered'><div class='code-highlight-line'> [...]
</div></div><div data-line='5' class='code-highlight-row numbered'><div class='code-highlight-line'> </div></div><div data-line='6' class='code-highlight-row numbered'><div class='code-highlight-line'> # We don't need new action to be defined
</div></div><div data-line='7' class='code-highlight-row numbered'><div class='code-highlight-line'> </div></div><div data-line='8' class='code-highlight-row numbered'><div class='code-highlight-line'> def create
</div></div><div data-line='9' class='code-highlight-row numbered'><div class='code-highlight-line'> @product.attributes = params[:product]
</div></div><div data-line='10' class='code-highlight-row numbered'><div class='code-highlight-line'> # Here we need to reject blank categories
</div></div><div data-line='11' class='code-highlight-row numbered'><div class='code-highlight-line'> @product.categories.reject!(&:blank?)
</div></div><div data-line='12' class='code-highlight-row numbered'><div class='code-highlight-line'> if @product.save
</div></div><div data-line='13' class='code-highlight-row numbered'><div class='code-highlight-line'> flash[:notice] = I18n.t('product.create.success')
</div></div><div data-line='14' class='code-highlight-row numbered'><div class='code-highlight-line'> redirect_to(:action => :index)
</div></div><div data-line='15' class='code-highlight-row numbered'><div class='code-highlight-line'> else
</div></div><div data-line='16' class='code-highlight-row numbered'><div class='code-highlight-line'> render :action => :new
</div></div><div data-line='17' class='code-highlight-row numbered'><div class='code-highlight-line'> end
</div></div><div data-line='18' class='code-highlight-row numbered'><div class='code-highlight-line'> end
</div></div><div data-line='19' class='code-highlight-row numbered'><div class='code-highlight-line'> </div></div><div data-line='20' class='code-highlight-row numbered'><div class='code-highlight-line'> [...]
</div></div><div data-line='21' class='code-highlight-row numbered'><div class='code-highlight-line'> </div></div><div data-line='22' class='code-highlight-row numbered'><div class='code-highlight-line'> private
</div></div><div data-line='23' class='code-highlight-row numbered'><div class='code-highlight-line'> def load_product
</div></div><div data-line='24' class='code-highlight-row numbered'><div class='code-highlight-line'> @product = Product.new
</div></div><div data-line='25' class='code-highlight-row numbered'><div class='code-highlight-line'> end
</div></div><div data-line='26' class='code-highlight-row numbered'><div class='code-highlight-line'>end</div></div></pre></div>