4

I'm building a hierarchical category in Rails using Ancestry, and I allow the user to choose the parent of the object they're creating. I display the existing categories using a dropdown:

<%= f.input :ancestry, collection: Category.sorted_list %>

As long as the user chooses an existing node, all is well. If the user chooses the blank in the dropdown, I would expect Ancestry to create a root node, but instead the form throws an "is invalid" error.

My controller isn't doing anything mindblowing:

def update
  @category = Category.find(params[:id])

  respond_to do |format|
    if @category.update_attributes(params[:category])        
      format.html { redirect_to @category, notice: 'Category was successfully updated.' }        
      format.json { head :no_content }
    else        
      format.html { render action: "edit" }
      format.json { render json: @category.errors, status: :unprocessable_entity }
    end     
  end 
end 

I'm newer to Rails, so I'm not sure how to attack this problem. Is there a configuration for Ancestry that I missed, or is this a form validator being over-protective perhaps?

kid_drew
  • 3,857
  • 6
  • 28
  • 38

2 Answers2

8

That happens because ancestry can't be nil and it's a bad idea to change it manually because all the gem's behavior is based on this attribute. For such cases gem has another parent_id attribute which you should use in your form.

There is a good explanation in gem's wiki how to build form using ancestry

Hope it helps

Sergey Kishenin
  • 5,099
  • 3
  • 30
  • 50
  • So maybe I just don't understand how to set up a Category model correctly, then. If I add a :parent_id select to my form, I get a "Can't mass-assign protected attributes: parent_id" error from the controller. Do I need to have both an ancestry AND a parent_id column? – kid_drew Feb 26 '13 at 18:49
  • 1
    You dont need to have `parent_id` in your database, just `ancestry` column. But you have to put `parent_id` to `attr_accessible` to avoid mass-assignment error – Sergey Kishenin Feb 26 '13 at 19:31
1

Ancestry validates his field with this:

# Validate format of ancestry column value
validates_format_of ancestry_column, :with => Ancestry::ANCESTRY_PATTERN, :allow_nil => true

But you can't pass nil value in forms. So I did this:

before_validation do
  self.ancestry = nil if self.ancestry.blank?
end
Artem P
  • 5,198
  • 5
  • 40
  • 44