<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -51,10 +51,11 @@ class TagsController &lt; ApplicationController
       # strip out any spaces / newlines in values (model handles punctuation, etc, if found)
       values.map! {|v| v.gsub(&quot;\n&quot;,'').gsub(' ','') }
 
-      if @data_object.tag key, values, current_user
+      begin
+        @data_object.tag key, values, current_user
         flash[:notice] = 'New tag was successfully created'
-      else
-        # 
+      rescue FailedToCreateTag =&gt; e
+        flash[:notice] = e.message
       end
     end
     redirect_to request.referer ? :back : data_object_tags_path(@data_object.id)
@@ -85,7 +86,6 @@ class TagsController &lt; ApplicationController
 
       @tags = DataObjectTags.find_all_by_data_object_id_and_data_object_tag_id(@data_object.id, @tag.id)
 
-      #if @data_object.has_tag?@tag
       if @tags
         # render :text =&gt; &quot;DataObject is tagged with #{ params[:id] }&quot;
         @my_tag = @tags.find {|t| current_user &amp;&amp;  t.user_id == current_user.id }</diff>
      <filename>app/controllers/tags_controller.rb</filename>
    </modified>
    <modified>
      <diff>@@ -103,9 +103,11 @@ class TaxaController &lt; ApplicationController
 
           # default to regular page separator if we can't find a specific kingdom
           @page_separator=&quot;page-separator-general&quot;
-          @page_separator=&quot;page-separator-#{@taxon_concept.kingdom.id}&quot; unless @taxon_concept.kingdom.nil? || !$KINGDOM_IDs.include?(@taxon_concept.kingdom.id.to_s)
+          @page_separator=&quot;page-separator-#{@taxon_concept.kingdom.id}&quot; unless
+            @taxon_concept.kingdom.nil? || !$KINGDOM_IDs.include?(@taxon_concept.kingdom.id.to_s)
 
-          @content     = @taxon_concept.content_by_category(@category_id) unless @category_id.nil? || @taxon_concept.table_of_contents(:vetted_only=&gt;current_user.vetted).blank?
+          @content     = @taxon_concept.content_by_category(@category_id) unless
+            @category_id.nil? || @taxon_concept.table_of_contents(:vetted_only=&gt;current_user.vetted).blank?
           @random_taxa = RandomTaxon.random_set(5)
 
           @ping_host_urls = @taxon_concept.ping_host_urls
@@ -147,99 +149,6 @@ class TaxaController &lt; ApplicationController
       end
     end
 
-#    respond_to do |format|
-#      # TODO - please, please, PLEASE refactor this.  There is WAY too much going on in this controller.
-#      format.html do
-#        @specify_category_id=params[:category_id] || 'default'
-#
-#        # reset the content level if it is in the querystring NOTE the expertise level is set by pre filter set_user_settings()
-#        current_user.content_level = params[:content_level] if ['1','2','3','4'].include?(params[:content_level])
-#
-#        begin
-#          @taxon = TaxonConcept.find(@taxon_id)
-#          @taxon.current_user = current_user
-#        rescue ActiveRecord::RecordNotFound
-#          raise &quot;taxa does not exist&quot;
-#        end
-#
-#        @curator = current_user.can_curate?(@taxon)
-#
-#        # run all the queries if the page cannot be cached or the fragment is not found
-#        if !allow_page_to_be_cached? || @specify_category_id != 'default' || !read_fragment(:controller=&gt;'taxa',:part=&gt;'page_' + @taxon_id.to_s + '_' + current_user.language_abbr + '_' + current_user.expertise.to_s + '_' + current_user.vetted.to_s + '_' + current_user.default_taxonomic_browser.to_s + '_' + current_user.can_curate?(@taxon).to_s)
-#
-#          @cached=false
-#
-#          @taxon.current_user = current_user
-#
-#          # get available media types
-#          @available_media = @taxon.available_media
-#
-#          # TODO - all these @taxon.videos/images/etc don't need to be full-class @variables.... just use taxon!
-#
-#          # get videos for this taxon
-#          @videos=@taxon.videos if @available_media[:video]
-#
-#          # get first set of images and if more images are available (for paging)
-#          # TODO - this (image_page) is broken.  Can we remove it?
-#          @image_page = (params[:image_page] || 1).to_i
-#          @taxon.current_agent = current_agent unless current_agent.nil?
-#          @images     = @taxon.images.sort{ |x,y| y.data_rating &lt;=&gt; x.data_rating }
-#          @show_next_image_page_button = @taxon.more_images # indicates if more images are available
-#          @default_image = @images[0].smart_image unless @images.nil? or @images.blank?
-#
-#          # find first valid content area to use
-#          first_content_item = @taxon.table_of_contents(:vetted_only=&gt;current_user.vetted, :agent_logged_in =&gt; agent_logged_in?).detect {|item| item.has_content? }
-#          @category_id = first_content_item.nil? ? nil : first_content_item.id
-#          @category_id = @specify_category_id unless @specify_category_id=='default'
-#
-#          @new_text_tocitem_id = get_new_text_tocitem_id(@category_id)
-#
-#          # default to regular page separator if we can't find a specific kingdom
-#          @page_separator=&quot;page-separator-general&quot;
-#          @page_separator=&quot;page-separator-#{@taxon.kingdom.id}&quot; unless @taxon.kingdom.nil? || !$KINGDOM_IDs.include?(@taxon.kingdom.id.to_s)
-#
-#          @content     = @taxon.content_by_category(@category_id) unless @category_id.nil? || @taxon.table_of_contents(:vetted_only=&gt;current_user.vetted).blank?
-#          @random_taxa = RandomTaxon.random_set(5)
-#
-#          @ping_host_urls = @taxon.ping_host_urls
-#
-#          # just grab the first rank name (will be &quot;taxon&quot; if no rank available)
-#          @rank=@taxon.hierarchy_entries[0].rank_label.capitalize
-#
-#          # log data objects shown and build an array of data_object_ids to log, so we can stick this info in the cached page and when the page comes from the cache, we can log on the server side
-#          @data_object_ids_to_log=Array.new
-#          unless @images.blank?
-#            log_data_objects_for_taxon_concept @taxon, @images.first
-#            @data_object_ids_to_log &lt;&lt; @images.first.id
-#          end
-#          unless @content.nil? || @content[:data_objects].blank?
-#            log_data_objects_for_taxon_concept @taxon, *@content[:data_objects]
-#            @content[:data_objects].each {|data_object| @data_object_ids_to_log &lt;&lt; data_object.id }
-#          end
-#          @data_object_ids_to_log.compact!
-#
-#          @contains_unvetted_objects = false # per request by Jim Edwards on 11/5/2008 in Mexico, we should *not* show the top banner indicating there are unvetted objects on a page
-#          #@contains_unvetted_objects=((!current_user.vetted &amp;&amp; @taxon.includes_unvetted) ? true : false)  # uncomment this line to show unvetted warning on page with those objects
-#
-#        else
-#
-#          @cached=true
-#
-#        end # end get full page since we couldn't read from cache
-#
-#        @taxon_page_title=remove_html(@taxon.title) # we always need the title
-#
-#        render :template=&gt;'/taxa/show_cached' if allow_page_to_be_cached? &amp;&amp; @specify_category_id == 'default' # if caching is allowed, see if fragment exists using this template
-#      end
-#      format.xml do
-#        xml = Rails.cache.fetch(&quot;taxon.#{@taxon_id}/xml&quot;, :expires_in =&gt; 4.hours) do
-#          TaxonConcept.find(@taxon_id).to_xml(:full =&gt; true)
-#        end
-#        render :xml =&gt; xml
-#      end
-#      # TODO - format.json { render :json =&gt; @species.to_json }
-#    end
-
   end
 
   # execute search and show results</diff>
      <filename>app/controllers/taxa_controller.rb</filename>
    </modified>
    <modified>
      <diff>@@ -2,8 +2,8 @@ require 'set'
 require 'uuid'
 require 'erb'
 
-# Represents any kind of object imported from a ContentPartner, eg. an image, article, video, etc.  This is one of our primary
-# models, and an awful lot of work occurs here.
+# Represents any kind of object imported from a ContentPartner, eg. an image, article, video, etc.  This is one
+# of our primary models, and an awful lot of work occurs here.
 class DataObject &lt; SpeciesSchemaModel
   
   include UserActions
@@ -326,9 +326,26 @@ class DataObject &lt; SpeciesSchemaModel
     end
   end
 
-  # tag with a DataObjectTag
+  # add a DataObjectTag to a DataObject
   def tag(key, values, user = nil)
-    DataObject.tag self, key, values, user
+    values = [values.to_s] unless values.is_a?Array
+    if key and values
+      values.each do |value|
+        tag    = DataObjectTag.find_or_create_by_key_and_value key.to_s, value.to_s
+        if user.tags_are_public_for_data_object?(self)
+          tag.is_public = true
+          tag.save!
+        end
+        join   = DataObjectTags.new :data_object =&gt; self, :data_object_tag =&gt; tag, :user =&gt; user
+        begin
+          join.save!
+        rescue # TODO LOWPRIO - specific rescue types with nice, customer-facing explanations.
+          raise FailedToCreateTag.new(&quot;Failed to add #{key}:#{value} tag&quot;)
+        end
+      end
+      tags.reset
+      user.tags.reset if user # TODO - can we tag anonymously?  If not, clean this up to reflect that.
+    end
   end
 
   def public_tags
@@ -669,20 +686,6 @@ AND data_type_id IN (:data_type_ids)
     ActiveRecord::Base.sanitize_sql([query_string, {:taxon_concept_id =&gt; taxon.id, :data_type_ids =&gt; DataObject.get_type_ids(type)}])
   end
 
-
-
-
-#  select dt.label media_type, dato.*, '' scientific_name
-#from data_objects dato
-#straight_join eol_development.users_data_objects udo ON (dato.id=udo.data_object_id)
-#straight_join data_types dt ON (dato.data_type_id = dt.id)
-#where
-#udo.taxon_concept_id=2
-#and data_type_id IN(3);
-#
-
-
-
   alias :ar_to_xml :to_xml
   # Be careful calling a block here.  We have our own builder, and you will be overriding that if you use a block.
   def to_xml(options = {})
@@ -747,6 +750,8 @@ private
                   #AND ar.agent_id = #{agent.id}  -- We removed this because now we're filtering manually.
   end
 
+  # TODO - this smells like a good place to use a Strategy pattern.  The user can have certain behaviour based
+  # on their access.
   def self.visibility_clause(options)
     preview_objects = ActiveRecord::Base.sanitize_sql(['OR (dato.visibility_id = ? AND dato.published IN (0,1))', Visibility.preview.id])
     published    = [1] # Boolean
@@ -797,31 +802,6 @@ EOVISBILITYCLAUSE
     end
   end
 
-  # add a DataObjectTag to a DataObject
-  #
-  # JRice asks: why is this a class method?  One necessarily passes a data_object as the first argument, so
-  # it seems to me that this is superfluous...
-  # 
-  # returns true is a tag was successfully added, else false
-  def self.tag data_object, key, values, user = nil
-    values = [values.to_s] unless values.is_a?Array
-    results = []
-    if data_object and key and values
-      values.each do |value|
-        tag    = DataObjectTag.find_or_create_by_key_and_value key.to_s, value.to_s
-        if user.tags_are_public_for_data_object?(data_object)
-          tag.is_public = true
-          tag.save!
-        end
-        join   = DataObjectTags.new :data_object =&gt; data_object, :data_object_tag =&gt; tag, :user =&gt; user
-        results &lt;&lt; join.save
-      end
-      data_object.tags.reset
-      user.tags.reset if user
-    end
-    ( ! results.include?false ) # return true or false based on whether the new tag association was created OK
-  end
-
 end
 # == Schema Info
 # Schema version: 20081020144900</diff>
      <filename>app/models/data_object.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,5 @@
-# Represents the vague idea of a Taxon.
+# Represents a group of HierearchyEntry instances that we consider &quot;the same&quot;.  This amounts to a vague idea
+# of a taxon, which we serve as a single page.
 #
 # We get different interpretations of taxa from our partners (ContentPartner), often differing slightly 
 # and referring to basically the same thing, so TaxonConcept was created as a means to reconcile the 
@@ -33,10 +34,6 @@ class TaxonConcept &lt; SpeciesSchemaModel
 
   attr_reader :has_media
 
-  ##################################### 
-  # The following are the &quot;nice&quot; methods, which we want to publically expose.  ...As opposed to the down-and-dirty stuff that we
-  # want to shamefully hide.  These are the methods from which we can build nice, clean objects to serve to the general public:
-
   def show_curator_controls?(user = nil)
     return @show_curator_controls if !@show_curator_controls.nil?
     user = @current_user if user.nil?
@@ -51,10 +48,14 @@ class TaxonConcept &lt; SpeciesSchemaModel
     table_of_contents.each do |toc|
       return toc if toc.allow_user_text?
     end
-    TocItem.find_by_sql('select t.id, t.parent_id, t.label, t.view_order from table_of_contents t, info_items i where i.toc_id=t.id limit 1')[0]
+    TocItem.find_by_sql('SELECT t.id, t.parent_id, t.label, t.view_order
+                         FROM table_of_contents t, info_items i
+                         WHERE i.toc_id=t.id
+                         LIMIT 1')[0]
   end
 
-  # The canonical form is the simplest string we can use to identify a species--no variations, no attribution, nothing fancy:
+  # The canonical form is the simplest string we can use to identify a species--no variations, no attribution, nothing
+  # fancy:
   def canonical_form
     return name(:canonical)
   end
@@ -182,15 +183,11 @@ class TaxonConcept &lt; SpeciesSchemaModel
     end)
   end
 
-  ##################################### 
-  # The rest of these methods are shamefully complex and probably require serious refactoring.
-
   # Try not to call this unless you know what you're doing.  :) See scientific_name and common_name instead.
   #
-  # That said, this method allows you to get other variations on a name.  See HierarchyEntry#name, to which this is really
-  # delegating, unless there is no entry in the default Hierarchy, in which case, see #alternate_classification_name.
-  #
-  # (Hey, I warned you these methods were ugly.)
+  # That said, this method allows you to get other variations on a name.  See HierarchyEntry#name, to which this is
+  # really delegated, unless there is no entry in the default Hierarchy, in which case, see
+  # #alternate_classification_name.
   def name(detail_level = :middle, language = Language.english, context = nil)
     col_he = hierarchy_entries.detect {|he| he.hierarchy_id == Hierarchy.default.id }
     return col_he.nil? ? alternate_classification_name(detail_level, language, context).firstcap : col_he.name(detail_level, language, context).firstcap</diff>
      <filename>app/models/taxon_concept.rb</filename>
    </modified>
    <modified>
      <diff>@@ -13,7 +13,7 @@ truncate_all_tables_once
 EOL::Scenario.load :foundation
 
 Given /^a Taxon Concept (.*)$/ do |tc_id|
-  @taxon_concept = build_taxon_concept(:id =&gt; tc_id)
+  @taxon_concept = build_taxon_concept(:id =&gt; tc_id, :common_name =&gt; 'vulcan')
 end
 
 Given /Taxon Concept (.*) has an image with key &quot;(.*)&quot; harvested from (.*) with a ping_host_url of &quot;(.*)&quot;/ do</diff>
      <filename>features/step_definitions/builder_steps.rb</filename>
    </modified>
    <modified>
      <diff>@@ -108,7 +108,8 @@ class EOL
       options =
         default_attributes.merge({:data_type   =&gt; DataType.find_by_label(@type),
                                   :description =&gt; desc,
-                                  :mime_type   =&gt; mime_types[@type] || mime_type[:default]})
+                                  :mime_type   =&gt; MimeType.find_by_label(mime_types[@type] || mime_type[:default])
+                                 })
       if @type == 'Image'
          options[:object_cache_url] ||= Factory.next(:image)
       end
@@ -171,15 +172,15 @@ class EOL
     # class is *used*... which makes sense, it relies on foundation in many other ways.
     def mime_types
       @mime_types ||= {
-        'Image'      =&gt; MimeType.find_by_label('image/jpeg'),
-        'Sound'      =&gt; MimeType.find_by_label('audio/mpeg'),
-        'Text'       =&gt; MimeType.find_by_label('text/html'),
-        'Video'      =&gt; MimeType.find_by_label('video/quicktime'),
-        'GBIF Image' =&gt; MimeType.find_by_label('image/jpeg'),
-        'IUCN'       =&gt; MimeType.find_by_label('text/plain'),
-        'Flash'      =&gt; MimeType.find_by_label('video/x-flv'),
-        'YouTube'    =&gt; MimeType.find_by_label('video/x-flv'),
-        :default     =&gt; MimeType.find_by_label('image/jpeg')
+        'Image'      =&gt; 'image/jpeg',
+        'Sound'      =&gt; 'audio/mpeg',
+        'Text'       =&gt; 'text/html',
+        'Video'      =&gt; 'video/quicktime',
+        'GBIF Image' =&gt; 'image/jpeg',
+        'IUCN'       =&gt; 'text/plain',
+        'Flash'      =&gt; 'video/x-flv',
+        'YouTube'    =&gt; 'video/x-flv',
+        :default     =&gt; 'image/jpeg'
       }
     end
     def default_attributes</diff>
      <filename>lib/eol/data_object_builder.rb</filename>
    </modified>
    <modified>
      <diff>@@ -17,7 +17,7 @@ class EOL
     #     String to use for canonical form (all names will reference this)
     #   +comments+::
     #     Array of hashes.  Each hash can have a +:body+ and +:user+ key.
-    #   +common_name+::
+    #   +common_names+::
     #     String to use for thre preferred common name
     #   +depth+::
     #     Depth to apply to the attached hierarchy entry.  Don't supply this AND rank.
@@ -105,8 +105,10 @@ class EOL
       @he    = build_entry_in_hierarchy(:parent_id =&gt; @options[:parent_hierarchy_entry_id])
       TaxonConceptName.gen(:preferred =&gt; true, :vern =&gt; false, :source_hierarchy_entry_id =&gt; @he.id,
                            :language =&gt; Language.scientific, :name =&gt; @sname, :taxon_concept =&gt; @tc)
-      TaxonConceptName.gen(:preferred =&gt; true, :vern =&gt; true, :source_hierarchy_entry_id =&gt; @he.id,
-                           :language =&gt; Language.english, :name =&gt; @cname, :taxon_concept =&gt; @tc)
+      unless @cname.nil?
+        TaxonConceptName.gen(:preferred =&gt; true, :vern =&gt; true, :source_hierarchy_entry_id =&gt; @he.id,
+                             :language =&gt; Language.english, :name =&gt; @cname, :taxon_concept =&gt; @tc)
+      end
       # TODO - create the Synonym here, with the Language of English, the SynonymRelation of Common Name, and the HE we just
       # created, and preferred...
       # NOTE: when we denormalize the taxon_concept_names table, we should be looking at Synonyms as well as Names.
@@ -114,17 +116,7 @@ class EOL
 
     def add_curator
       puts &quot;** Enter: add_curator&quot; if @debugging
-      @curator = Factory(:curator, :curator_hierarchy_entry =&gt; @he)
-      if @debugging
-        puts &quot;&amp;&amp; TC:&quot;
-        pp @tc
-        puts &quot;&amp;&amp; Curator:&quot;
-        pp @curator
-        puts &quot;&amp;&amp; TC.Curators:&quot;
-        pp @tc.curators
-        puts &quot;&amp;&amp; TC.Acting Curators:&quot;
-        pp @tc.acting_curators
-      end
+      @curator = build_curator(@he)
     end
 
     def add_comments
@@ -212,12 +204,14 @@ class EOL
 
     def gen_random_taxa
       puts &quot;** Enter: gen_random_taxa&quot; if @debugging
-      return if @images.blank? or @sname.blank? or @cname.blank?
+      return if @images.blank? or @sname.blank?
       # TODO - we really don't want to denomalize the names, so remove them (but check that this will work!)
-      RandomTaxon.gen(:language =&gt; Language.english, :data_object =&gt; @images.last, :name_id =&gt; @sname.id,
-                      :image_url =&gt; @images.last.object_cache_url, :name =&gt; @sname.italicized, :content_level =&gt; 4,
-                      :taxon_concept =&gt; @tc, :common_name_en =&gt; @cname.string,
-                      :thumb_url =&gt; @images.first.object_cache_url) # TODO - not sure thumb_url is right.
+      options = {:language =&gt; Language.english, :data_object =&gt; @images.last, :name_id =&gt; @sname.id,
+                 :image_url =&gt; @images.last.object_cache_url, :name =&gt; @sname.italicized, :content_level =&gt; 4,
+                 :taxon_concept =&gt; @tc,
+                 :thumb_url =&gt; @images.first.object_cache_url}
+      options[:common_name_en] = @cname.string unless @cname.blank?
+      RandomTaxon.gen(options)
     end
 
     # TODO - This is one of the slower methods.
@@ -257,11 +251,11 @@ class EOL
     # TODO - Too long: break this up
     def set_default_options
       puts &quot;** Enter: set_default_options&quot; if @debugging
-      @attri       = @options[:attribution]     || Factory.next(:attribution)
-      @common_name = @options[:common_name]     || Factory.next(:common_name)
-      @canon       = @options[:canonical_form]  || Factory.next(:scientific_name)
-      @complete    = @options[:scientific_name] || &quot;#{@canon} #{@attri}&quot;.strip
-      @hierarchy   = @options[:hierarchy]       || nil # We'll let build_hierarchy_entry pick a default
+      @attri        = @options[:attribution]     || Factory.next(:attribution)
+      @common_names = @options[:common_names]    || [] # MOST entries should NOT have a common name.
+      @canon        = @options[:canonical_form]  || Factory.next(:scientific_name)
+      @complete     = @options[:scientific_name] || &quot;#{@canon} #{@attri}&quot;.strip
+      @hierarchy    = @options[:hierarchy]       || nil # We'll let build_hierarchy_entry pick a default
       @event = @options[:event] || default_harvest_event
       @images = [] # This is used to build the RandomTaxon
       if @options[:toc].nil?
@@ -304,9 +298,12 @@ class EOL
       @cform = CanonicalForm.find_by_string(@canon) || CanonicalForm.gen(:string =&gt; @canon)
       @sname = Name.gen(:canonical_form =&gt; @cform, :string =&gt; @complete,
                         :italicized     =&gt; @options[:italicized] || &quot;&lt;i&gt;#{@canon}&lt;/i&gt; #{@attri}&quot;.strip)
-      # TODO - You don't always need a common name, and in fact most don't; default should be NOT to have one
       # TODO - This should also create an entry in Synonyms (see below) (don't need agents_synonyms though)
-      @cname = Name.gen(:canonical_form =&gt; @cform, :string =&gt; @common_name, :italicized =&gt; @common_name)
+      cname_objects = []
+      @common_names.each do |common_name|
+        cname_objects &lt;&lt; Name.gen(:canonical_form =&gt; @cform, :string =&gt; common_name, :italicized =&gt; common_name)
+      end
+      @cname = cname_objects.first
     end
 
   end</diff>
      <filename>lib/eol/taxon_concept_builder.rb</filename>
    </modified>
    <modified>
      <diff>@@ -56,26 +56,31 @@ gbif_agent = Agent.gen(:full_name =&gt; &quot;Global Biodiversity Information Facility (
 AgentContact.gen(:agent =&gt; gbif_agent, :agent_contact_role =&gt; AgentContactRole.primary)
 gbif_hierarchy = Hierarchy.gen(:agent =&gt; gbif_agent, :label =&gt; &quot;GBIF Nub Taxonomy&quot;)
 
-kingdom = build_taxon_concept(:rank =&gt; 'kingdom', :canonical_form =&gt; 'Animalia', :common_name =&gt; 'Animals')
+kingdom = build_taxon_concept(:rank =&gt; 'kingdom', :canonical_form =&gt; 'Animalia', :common_names =&gt; ['Animals'])
 4.times do
   build_taxon_concept(:parent_hierarchy_entry_id =&gt; Hierarchy.default.hierarchy_entries.last.id,
-                      :depth =&gt; Hierarchy.default.hierarchy_entries.length)
+                      :depth =&gt; Hierarchy.default.hierarchy_entries.length,
+                      :common_names =&gt; [Factory.next(:common_name)])
 end
 
 fifth_entry_id = Hierarchy.default.hierarchy_entries.last.id
 depth_now      = Hierarchy.default.hierarchy_entries.length
 
-# Sixth Taxon should have more images:
-tc = build_taxon_concept(:parent_hierarchy_entry_id =&gt; fifth_entry_id,
-                    :depth =&gt; depth_now, :images =&gt; [{}, {}, {}, {}, {}, {}, {}, {}, {}, {}])
+# Sixth Taxon should have more images, and have videos:
+tc = build_taxon_concept(:parent_hierarchy_entry_id =&gt; fifth_entry_id, :common_names =&gt; [Factory.next(:common_name)],
+                         :depth =&gt; depth_now, :images =&gt; [{}, {}, {}, {}, {}, {}, {}, {}, {}, {}])
 
 # Seventh Taxon (sign of the apocolypse?) should be a child of fifth and be &quot;empty&quot;, other than common names:
-build_taxon_concept(:parent_hierarchy_entry_id =&gt; fifth_entry_id,
+build_taxon_concept(:parent_hierarchy_entry_id =&gt; fifth_entry_id, :common_names =&gt; [Factory.next(:common_name)],
                     :depth =&gt; depth_now, :images =&gt; [], :toc =&gt; [], :flash =&gt; [], :youtube =&gt; [], :comments =&gt; [],
                     :bhl =&gt; [])
 
 # Eighth Taxon (now we're just getting greedy) should be the same as Seven, but with BHL:
-build_taxon_concept(:parent_hierarchy_entry_id =&gt; fifth_entry_id,
+build_taxon_concept(:parent_hierarchy_entry_id =&gt; fifth_entry_id, :common_names =&gt; [Factory.next(:common_name)],
+                    :depth =&gt; depth_now, :images =&gt; [], :toc =&gt; [], :flash =&gt; [], :youtube =&gt; [], :comments =&gt; [])
+
+# Ninth Taxon is *totally* naked:
+build_taxon_concept(:parent_hierarchy_entry_id =&gt; fifth_entry_id, :common_names =&gt; [],
                     :depth =&gt; depth_now, :images =&gt; [], :toc =&gt; [], :flash =&gt; [], :youtube =&gt; [], :comments =&gt; [])
 
 # Now that we're done with CoL, we add another content partner who overlaps with them:
@@ -113,7 +118,7 @@ curator.save
 make_all_nested_sets
 recreate_normalized_names_and_links
 
-exemplar = build_taxon_concept(:id =&gt; 910093) # That ID is one of the (hard-coded) exemplars.
+exemplar = build_taxon_concept(:common_names =&gt; ['wumpus'], :id =&gt; 910093) # That ID is one of the (hard-coded) exemplars.
 
 # Adds a ContentPage at the following URL: http://localhost:3000/content/page/curator_central
 </diff>
      <filename>scenarios/bootstrap.rb</filename>
    </modified>
    <modified>
      <diff>@@ -6,8 +6,8 @@ describe 'Account user profile page (HTML)' do
 
   before(:all) do
     @credentials = 'This has a &lt;a href=&quot;linky&quot;&gt;link&lt;/a&gt; &lt;b&gt;this is bold&lt;br /&gt;as is this&lt;/b&gt; and &lt;script type=&quot;text/javascript&quot;&gt;alert(&quot;hi&quot;);&lt;/script&gt;'
-    @user = Factory(:curator, :credentials =&gt; @credentials)
-    @result        = RackBox.request(&quot;/account/show/#{@user.id}&quot;) # cache the response the taxon page gives before changes
+    @user        = build_curator(HierarchyEntry.gen, :credentials =&gt; @credentials)
+    @result      = RackBox.request(&quot;/account/show/#{@user.id}&quot;) # cache the response the taxon page gives before changes
   end
 
   it 'should allow links in credentials' do</diff>
      <filename>spec/blackbox/account_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -19,7 +19,7 @@ describe 'Content Partner Pages' do
       # @another_taxon_concept = build_taxon_concept
       # @user             = User.gen
       # @short_comment_from_user = 'Comment from user'
-      # @curator          = Factory(:curator)
+      # @curator          = build_curator(@taxon_concept)
       # @taxon_concept.images.first.comment(@user, @short_comment_from_user)
       # login_content_partner(:username =&gt; @content_partner.username,
       #                       :password =&gt; password)</diff>
      <filename>spec/blackbox/content_partner_pages_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -7,7 +7,7 @@ def curator_for_taxon_id(id)
 end
 
 def create_curator_for_taxon_concept(tc)
- user =  Factory(:curator, :curator_hierarchy_entry =&gt; tc.entry)
+ user =  build_curator(tc)
  tc.images.last.curator_activity_flag user, tc.id
  return user
 end
@@ -74,7 +74,7 @@ describe 'Curation' do
   it 'should change the number of curators if another curator curates an image' do
     num_curators = @taxon_concept.acting_curators.length
     @default_page.body.should have_tag('div#number-of-curators', /#{num_curators}/)
-    user = Factory(:curator, :curator_hierarchy_entry =&gt; @taxon_concept.entry)
+    user = build_curator(@taxon_concept)
     @taxon_concept.images.last.curator_activity_flag user, @taxon_concept.id
     @taxon_concept.acting_curators.length.should == num_curators + 1
     request(&quot;/pages/#{@taxon_concept.id}&quot;).body.should have_tag('div#number-of-curators', /#{num_curators+1}/)
@@ -83,7 +83,7 @@ describe 'Curation' do
   it 'should change the number of curators if another curator curates a text object' do
     num_curators = @taxon_concept.acting_curators.length
     @default_page.body.should have_tag('div#number-of-curators', /#{num_curators}/)
-    user = Factory(:curator, :curator_hierarchy_entry =&gt; @taxon_concept.entry)
+    user = build_curator(@taxon_concept)
     @taxon_concept.overview.first.curator_activity_flag user, @taxon_concept.id
     @taxon_concept.acting_curators.length.should == num_curators + 1
     request(&quot;/pages/#{@taxon_concept.id}&quot;).body.should have_tag('div#number-of-curators', /#{num_curators+1}/)</diff>
      <filename>spec/blackbox/curation_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -16,15 +16,8 @@ describe 'Home page' do
     ActionController::Base.perform_caching = @old_cache_val
   end
 
-  it 'should say EOL somewhere' do
+  it 'should include the exemplar taxon concept' do
     @page.body.should include(@taxon_concept.scientific_name)
   end
 
-#  Trying to reproduce a bug and failing:
-#  it 'should load twice without dying' do
-#    @page.body.should include(@taxon_concept.scientific_name)
-#    page2 = RackBox.request('/content/exemplars') # cache the response the homepage gives before changes
-#    page2.body.should include(@taxon_concept.scientific_name)
-#  end
-
 end</diff>
      <filename>spec/blackbox/exemplars_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -39,42 +39,36 @@ describe 'Login' do
   end
 
   it 'should redirect to index after a successful login' do
-    @user = create_user 'charliebrown', 'testing'
-    login_as( @user ).should redirect_to('/')
+    user = create_user 'charliebrown', 'testing'
+    login_as(user).should redirect_to('/')
   end
 
   it 'should say hello to the user after logging in' do
-    @user = create_user 'charliebrown', 'testing'
-
-    request('/').should_not include_text(&quot;Hello #{ @user.given_name }&quot;)
-    login_as( @user ).should redirect_to('/')
-    request('/').should include_text(&quot;Hello #{ @user.given_name }&quot;)
+    user = create_user 'charliebrown', 'testing'
+    request('/').should_not include_text(&quot;Hello #{ user.given_name }&quot;)
+    login_as(user).should redirect_to('/')
+    request('/').should include_text(&quot;Hello #{ user.given_name }&quot;)
   end
   
   it 'logout should work' do
-    @user = create_user 'charliebrown', 'testing'
+    user = create_user 'charliebrown', 'testing'
 
-    login_as( @user ).should redirect_to('/')
-    request('/').should include_text(&quot;Hello #{ @user.given_name }&quot;)
+    login_as(user).should redirect_to('/')
+    request('/').should include_text(&quot;Hello #{ user.given_name }&quot;)
     request('/logout')
-    request('/').should_not include_text(&quot;Hello #{ @user.given_name }&quot;)
+    request('/').should_not include_text(&quot;Hello #{ user.given_name }&quot;)
   end
   
   it 'should not show the curator link' do
-    @user = create_user 'charliebrown', 'testing'
-    
-    login_as(@user)
+    user = create_user 'charliebrown', 'testing'
+    login_as(user)
     request('/').should_not include_text('curators')
   end
   
   describe &quot;as a curator&quot; do
     it &quot;should show the curator link&quot; do
-      @tc = build_taxon_concept()
-      @user = Factory(:curator, :username =&gt; 'test_curator',
-              :password =&gt; 'test_password',
-              :curator_hierarchy_entry =&gt; HierarchyEntry.gen(:taxon_concept =&gt; @tc))
-
-      login_as(@user)
+      curator = build_curator(HierarchyEntry.gen, :username =&gt; 'test_curator', :password =&gt; 'test_password')
+      login_as(curator)
       request('/').should include_text(&quot;curators&quot;)
     end
   end</diff>
      <filename>spec/blackbox/login_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -26,7 +26,7 @@ describe 'Search' do
   def create_taxa(namestring)
 
     taxa = build_taxon_concept(:canonical_form =&gt; namestring, :depth =&gt; 1,
-                                :parent_hierarchy_entry_id =&gt; SearchSpec.animal_kingdom.hierarchy_entries.first.id)
+                               :parent_hierarchy_entry_id =&gt; SearchSpec.animal_kingdom.hierarchy_entries.first.id)
     SearchSpec.nestify_everything_properly
     SearchSpec.recreate_normalized_names_and_links
     return taxa</diff>
      <filename>spec/blackbox/search_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -15,7 +15,7 @@ describe 'Taxa page (HTML)' do
     rescue
       #there's already a tc with that id
     end
-    @parent          = build_taxon_concept
+    @parent          = build_taxon_concept(:images =&gt; [], :toc =&gt; []) # Somewhat empty, to speed things up.
     @overview        = TocItem.overview
     @overview_text   = 'This is a test Overview, in all its glory'
     # TODO - add a reference to the text object
@@ -46,7 +46,7 @@ describe 'Taxa page (HTML)' do
        :attribution     =&gt; @attribution,
        :scientific_name =&gt; @scientific_name,
        :italicized      =&gt; @italicized,
-       :common_name     =&gt; @common_name,
+       :common_names    =&gt; [@common_name],
        :iucn_status     =&gt; @iucn_status,
        :map             =&gt; {:description =&gt; @map_text},
        :flash           =&gt; [{:description =&gt; @video_1_text}, {:description =&gt; @video_2_text}],
@@ -76,7 +76,7 @@ describe 'Taxa page (HTML)' do
     @description_link = /and &lt;a href=&quot;link&quot;&gt;links&lt;\/a&gt;/
     @taxon_concept.add_user_submitted_text(:description =&gt; description, :vetted =&gt; true)
 
-    @curator       = Factory(:curator, :curator_hierarchy_entry =&gt; @taxon_concept.entry)
+    @curator       = build_curator(@taxon_concept)
     Comment.find_by_body(@comment_bad).hide! User.last
     @result        = RackBox.request(&quot;/pages/#{@id}&quot;) # cache the response the taxon page gives before changes
 </diff>
      <filename>spec/blackbox/taxa_page_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -43,7 +43,7 @@ describe 'Taxa page XML' do
                          :attribution     =&gt; @attribution,
                          :scientific_name =&gt; @scientific_name,
                          :italicized      =&gt; @italicized,
-                         :common_name     =&gt; @common_name,
+                         :common_names    =&gt; [@common_name],
                          :iucn_status     =&gt; @iucn_status,
                          :map             =&gt; {:description =&gt; @map_text},
                          :flash           =&gt; [{:description =&gt; @video_1_text}, {:description =&gt; @video_2_text}],
@@ -59,7 +59,7 @@ describe 'Taxa page XML' do
     @child2        = build_taxon_concept(:parent_hierarchy_entry_id =&gt; @taxon_concept.hierarchy_entries.first.id)
     @id            = @taxon_concept.id
     @images        = @taxon_concept.images
-    @curator       = Factory(:curator, :curator_hierarchy_entry =&gt; @taxon_concept.entry)
+    @curator       = build_curator(@taxon_concept)
     Comment.find_by_body(@comment_bad).hide! User.last
   end
 </diff>
      <filename>spec/blackbox/taxa_page_xml_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -96,29 +96,65 @@ module EOL::Spec
     #
     #   +hierarchy+::
     #     Which Hierarchy to link this to.  Defaults to... uhhh... the default (Hierarchy#default).
+    #   +identifier+::
+    #     The &quot;foreign key&quot; that the Resource supplying this refers to this HE as, used for outlinking.
+    #   +map+::
+    #     If defined, this HE will be marked as having a map, otherwise marked as not having one.
     #   +parent_id+::
     #     Which HierarchyEntry (by *ID*, not object) this links to.
     #
     # TODO LOW_PRIO - the arguments to this method are lame and should be options with reasonable defaults.
     def build_hierarchy_entry(depth, tc, name, options = {})
-      he    = HierarchyEntry.gen(:hierarchy     =&gt; options[:hierarchy] || Hierarchy.default, # TODO - This should *really* be the H associated with the Resource that's being &quot;harvested&quot;... technically, CoL shouldn't even have HEs...
-                                 :parent_id     =&gt; options[:parent_id] || 0,
-                                 :identifier    =&gt; options[:identifier] || '', # This is the foreign ID native to the Resouce, not EOL.
-                                 :depth         =&gt; depth,
-                                 :rank_id       =&gt; depth + 1, # Cheating. As long as *we* created Ranks with a scenario, this works.
-                                 :taxon_concept =&gt; tc,
-                                 :name          =&gt; name)
-      HierarchiesContent.gen(:hierarchy_entry =&gt; he, :text =&gt; 1, :image =&gt; 1, :content_level =&gt; 4, :gbif_image =&gt; options[:map] ? 1 : 0,
-                             :youtube =&gt; 1, :flash =&gt; 1)
+      he = HierarchyEntry.gen(:hierarchy     =&gt; options[:hierarchy] || Hierarchy.default, # TODO - This should *really*
+                                # be the H associated with the Resource that's being &quot;harvested&quot;... technically, CoL
+                                # shouldn't even have Data Objects. Hierarchy.last may be clever enough, really.  I
+                                # just don't want to change this *right now*--I have other problems...
+                              :parent_id     =&gt; options[:parent_id] || 0,
+                              :identifier    =&gt; options[:identifier] || '',
+                              :depth         =&gt; depth,
+                              # Cheating. As long as *we* created Ranks with a scenario, this works:
+                              :rank_id       =&gt; depth + 1,
+                              :taxon_concept =&gt; tc,
+                              :name          =&gt; name)
+      HierarchiesContent.gen(:hierarchy_entry =&gt; he, :text =&gt; 1, :image =&gt; 1, :content_level =&gt; 4,
+                             :gbif_image =&gt; options[:map] ? 1 : 0, :youtube =&gt; 1, :flash =&gt; 1)
       # TODO - Create two AgentsHierarchyEntry(ies); you want &quot;Source Database&quot; and &quot;Compiler&quot; as roles
       return he
     end
 
     def build_taxon_concept(options = {})
-
       tc_builder = EOL::TaxonConceptBuilder.new(options)
       return tc_builder.tc
+    end
+
+    # Curators are tricky... not just a plain model, but require some activity before they are &quot;active&quot;:
+    # The first argument is the TaxonConcept or HierarchyEntry to associate the curator to; the second argument is
+    # the options hash to use when building the User model.
+    def build_curator(entry, options = {})
+      entry ||= Factory(:hierarchy_entry)
+      tc = nil # scope
+      if entry.class == TaxonConcept
+        tc    = entry
+        entry = tc.entry 
+      end
+      tc ||= entry.taxon_concept
+      options = {
+        :vetted                  =&gt; true,
+        :curator_hierarchy_entry =&gt; entry,
+        :curator_approved        =&gt; true,
+        :curator_scope           =&gt; ''
+      }.merge(options)
+
+      # These two do &quot;extra work&quot;, so I didn't want to use the merge on these (because they would be calculated even
+      # if not used:
+      options[:curator_verdict_by] ||= Factory(:user)
+      options[:curator_verdict_at] ||= 48.hours.ago
+
+      curator = User.gen(options)
 
+      # A curator isn't credited until she actually DOES something, which is handled thusly:
+      curator.last_curated_dates &lt;&lt; LastCuratedDate.gen(:taxon_concept =&gt; tc, :user =&gt; curator)
+      return curator
     end
 
     # Create a data object in the IUCN hierarchy. Can take options for :hierarchy and :event, both of which default to the usual IUCN
@@ -227,7 +263,7 @@ TaxonConcept.class_eval do
   #   +vetted+:
   #     The text object will only be visible if the user is logged in with &quot;All&quot; rather than &quot;Authoritative&quot; mode.
   #     Set this to true if you want it to be visible to &quot;Authoritative&quot;, or to remove the yellow background.
-  def add_user_submitted_text(options)
+  def add_user_submitted_text(options = {})
     options = {:description =&gt; 'some random text',
                :user        =&gt; User.last,
                :toc_item    =&gt; TocItem.overview,</diff>
      <filename>spec/eol_spec_helpers.rb</filename>
    </modified>
    <modified>
      <diff>@@ -386,33 +386,6 @@ Factory.define :content_section do |cs|
   cs.language_key 'en'
 end
 
-Factory.define :curator, :class =&gt; User do |u|
-  u.default_taxonomic_browser 'text'
-  u.expertise                 'middle'
-  u.remote_ip                 '128.167.250.123' # TODO - fake this?
-  u.content_level             2
-  u.email                     { Factory.next(:email) }
-  u.given_name                { Factory.next(:first_name) }
-  u.family_name               { Factory.next(:last_name) }
-  u.flash_enabled             true
-  u.language                  { Language.english || Factory(:language, :label =&gt; 'English') }
-  u.mailing_list              true
-  u.username                  {|user| &quot;#{user.given_name[0..0]}_#{user.family_name[0..9]}#{Factory.next(:int)}&quot;.gsub(/\s/, '_').downcase }
-  u.active                    true
-  u.password                  'test password'
-  u.vetted                    true
-  u.curator_hierarchy_entry   { Factory(:hierarchy_entry) }
-  u.curator_approved          true
-  u.curator_verdict_by        { Factory(:user) }
-  u.curator_verdict_at        { 48.hours.ago }
-  u.curator_scope             ''
-  # A curator isn't credited until she actually DOES something, which is handled thusly:
-  u.last_curated_dates        do |lcd|
-    [lcd.association(:last_curated_date,
-                     :taxon_concept =&gt; lcd.curator_hierarchy_entry.taxon_concept )]
-  end
-end
-
 Factory.define :curator_activity do |ca|
   ca.code { Factory.next(:string) }
 end
@@ -461,8 +434,8 @@ Factory.define :data_object do |dato|
   dato.created_at             { 5.days.ago }
   dato.updated_at             { 3.days.ago }
   dato.data_rating            0.0
-  dato.association            :vetted
-  dato.association            :visibility
+  dato.vetted                 { Vetted.trusted || Factory(:vetted, :label =&gt; 'trusted') }
+  dato.visibility             { Visibility.visible || Factory(:visibility, :label =&gt; 'visible') }
   dato.published              true
 end
 </diff>
      <filename>spec/factories.rb</filename>
    </modified>
    <modified>
      <diff>@@ -11,6 +11,17 @@ describe 'build_taxon_concept (spec helper method)' do
       :hierarchy =&gt; @hierarchy,
       :event     =&gt; @event
     )
+    @taxon_concept_naked = build_taxon_concept(
+      :images =&gt; [], :toc =&gt; [], :flash =&gt; [], :youtube =&gt; [], :comments =&gt; [], :bhl =&gt; []
+    )
+  end
+
+  it 'should be able to make a TC with no common names and an empty TOC' do
+    @taxon_concept_naked.table_of_contents.blank?.should be_true
+  end
+
+  it 'should not have a common name by defaut' do
+    @taxon_concept.common_name.blank?.should be_true
   end
 
   it 'should put all new hierarchy_entries under the default hierarchy if none supplied'  do</diff>
      <filename>spec/lib/taxon_concept_builder_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -10,7 +10,9 @@ def set_content_variables
 end
 
 def create_user_text_object
-  taxon_concept = build_taxon_concept(:rank =&gt; 'kingdom', :canonical_form =&gt; 'Animalia', :common_name =&gt; 'Animals')
+  taxon_concept = TaxonConcept.last ||
+                  build_taxon_concept(:rank =&gt; 'kingdom', :canonical_form =&gt; 'Animalia',
+                                      :common_names =&gt; ['Animals'])
   toc_item = TocItem.gen({:label =&gt; 'Overview'})
   params = {
     :taxon_concept_id =&gt; taxon_concept.id,
@@ -34,6 +36,13 @@ describe DataObject do
   truncate_all_tables
   Scenario.load :foundation # Just so we have DataType IDs and the like.
 
+  before(:all) do
+    unless @already_built_tc
+      build_taxon_concept
+    end
+    @already_built_tc = true
+  end
+
   describe 'ratings' do
 
     it 'should have a default rating of 2.5' do
@@ -101,7 +110,9 @@ describe DataObject do
 
     it 'should update existing data object' do
 
-      taxon_concept = build_taxon_concept(:rank =&gt; 'kingdom', :canonical_form =&gt; 'Animalia', :common_name =&gt; 'Animals')
+      taxon_concept = TaxonConcept.last ||
+                      build_taxon_concept(:rank =&gt; 'kingdom', :canonical_form =&gt; 'Animalia',
+                                          :common_names =&gt; ['Animals'])
       toc_item = TocItem.gen({:label =&gt; 'Overview'})
       params = {
         :taxon_concept_id =&gt; taxon_concept.id,
@@ -186,11 +197,10 @@ describe DataObject do
 
     it 'should mark tags as public if added by a curator' do
       commit_transactions # We're looking at curators, here, we need cross-database joins.
-      tc      = build_taxon_concept
-      curator = User.gen
-      dato    = tc.images.first # We CANNOT use @dato here, because it doesn't have all of the required
-                                # relationships to our TaxonConcept.
-      curator.approve_to_curate! tc.entry
+      tc      = TaxonConcept.last || build_taxon_concept
+      curator = build_curator(tc)
+      # We CANNOT use @dato here, because it doesn't have all of the required relationships to our TaxonConcept:
+      dato    = tc.add_user_submitted_text
       dato.tag 'color', 'blue', curator
       dotag = DataObjectTag.find_by_key_and_value('color', 'blue')
       DataObjectTag.find_by_key_and_value('color', 'blue').is_public.should be_true
@@ -336,16 +346,12 @@ describe DataObject do
     
     before(:each) do
       commit_transactions
-      @taxon_concept = build_taxon_concept
-      @data_object   = @taxon_concept.images.last
+      @taxon_concept = TaxonConcept.last || build_taxon_concept
       @user          = @taxon_concept.acting_curators.to_a.last
+      @data_object   = @taxon_concept.add_user_submitted_text(:user =&gt; @user)
       @num_lcd       = LastCuratedDate.count
     end
 
-    after(:all) do
-      truncate_all_tables
-    end
-    
     it 'should create a new LastCuratedDate pointing to the right TC and user' do
       @data_object.curator_activity_flag(@user, @taxon_concept.id)
       LastCuratedDate.count.should == @num_lcd + 1</diff>
      <filename>spec/models/data_object_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -10,6 +10,11 @@ require File.dirname(__FILE__) + '/../spec_helper'
 #
 describe Scenarios do
 
+  before(:all) do
+    truncate_all_tables # It is assumed you truncate the tables before you run these (well, before you expect them
+                        # to work!)
+  end
+
   # test the scenarios we want to make sure work
   %w( foundation bootstrap ).each do |scenario|
     it &quot;#{scenario} scenario should load without errors&quot; do</diff>
      <filename>spec/models/scenarios_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -44,7 +44,7 @@ describe TaxonConcept do
                              :attribution     =&gt; @attribution,
                              :scientific_name =&gt; @scientific_name,
                              :italicized      =&gt; @italicized,
-                             :common_name     =&gt; @common_name,
+                             :common_names    =&gt; [@common_name],
                              :gbif_map_id     =&gt; @gbif_map_id,
                              :flash           =&gt; [{:description =&gt; @video_1_text}, {:description =&gt; @video_2_text}],
                              :youtube         =&gt; [{:description =&gt; @video_3_text}],
@@ -56,7 +56,7 @@ describe TaxonConcept do
     @id            = tc.id
     @taxon_concept = TaxonConcept.find(@id)
     # The curator factory cleverly hides a lot of stuff that User.gen can't handle:
-    @curator       = Factory(:curator, :curator_hierarchy_entry =&gt; tc.entry)
+    @curator       = build_curator(@taxon_concept)
     # Curators aren't recognized until they actually DO something, which is here:
     LastCuratedDate.gen(:user =&gt; @curator, :taxon_concept =&gt; @taxon_concept)
     # And we want one comment that the world cannot see:
@@ -92,24 +92,16 @@ describe TaxonConcept do
 
   it 'should return overview as first toc item which accepts user submitted text' do
     @taxon_concept.tocitem_for_new_text.label.should == @overview.label
-    fifth_entry_id = Hierarchy.default.hierarchy_entries.last.id
-    depth_now      = Hierarchy.default.hierarchy_entries.length
-    tc = build_taxon_concept(:parent_hierarchy_entry_id =&gt; fifth_entry_id,
-                    :depth =&gt; depth_now, :images =&gt; [], :toc =&gt; [], :flash =&gt; [], :youtube =&gt; [], :comments =&gt; [],
-                    :bhl =&gt; [])
+    tc = build_taxon_concept(:images =&gt; [], :toc =&gt; [], :flash =&gt; [], :youtube =&gt; [], :comments =&gt; [], :bhl =&gt; [])
     tc.tocitem_for_new_text.label.should == @overview.label
   end
 
   it 'should return description as first toc item which accepts user submitted text' do
-    fifth_entry_id = Hierarchy.default.hierarchy_entries.last.id
-    depth_now      = Hierarchy.default.hierarchy_entries.length
     description_toc = TocItem.find_by_label('Description')
     InfoItem.gen(:toc_id =&gt; @overview.id)
     InfoItem.gen(:toc_id =&gt; description_toc.id)
-    tc = build_taxon_concept(:parent_hierarchy_entry_id =&gt; fifth_entry_id,
-                    :depth =&gt; depth_now, :images =&gt; [], :toc =&gt; [{:toc_item =&gt; description_toc, :description =&gt; 'huh?'}], :flash =&gt; [], :youtube =&gt; [], :comments =&gt; [],
-                    :bhl =&gt; [])
-
+    tc = build_taxon_concept(:images =&gt; [], :flash =&gt; [], :youtube =&gt; [], :comments =&gt; [], :bhl =&gt; [],
+                             :toc =&gt; [{:toc_item =&gt; description_toc, :description =&gt; 'huh?'}])
     tc.tocitem_for_new_text.label.should == description_toc.label
   end
 
@@ -191,10 +183,14 @@ describe TaxonConcept do
   end
 
   it 'should be able to list its children (NOT descendants, JUST children--animalia would be a disaster!)' do
-    @subspecies1  = build_taxon_concept(:rank =&gt; 'subspecies',   :depth =&gt; 0, :parent_hierarchy_entry_id =&gt; @taxon_concept.entry.id)
-    @subspecies2  = build_taxon_concept(:rank =&gt; 'subspecies',   :depth =&gt; 0, :parent_hierarchy_entry_id =&gt; @taxon_concept.entry.id)
-    @subspecies3  = build_taxon_concept(:rank =&gt; 'subspecies',   :depth =&gt; 0, :parent_hierarchy_entry_id =&gt; @taxon_concept.entry.id)
-    @infraspecies = build_taxon_concept(:rank =&gt; 'infraspecies', :depth =&gt; 0, :parent_hierarchy_entry_id =&gt; @subspecies1.entry.id)
+    @subspecies1  = build_taxon_concept(:rank =&gt; 'subspecies', :depth =&gt; 4,
+                                        :parent_hierarchy_entry_id =&gt; @taxon_concept.entry.id)
+    @subspecies2  = build_taxon_concept(:rank =&gt; 'subspecies', :depth =&gt; 4,
+                                        :parent_hierarchy_entry_id =&gt; @taxon_concept.entry.id)
+    @subspecies3  = build_taxon_concept(:rank =&gt; 'subspecies', :depth =&gt; 4,
+                                        :parent_hierarchy_entry_id =&gt; @taxon_concept.entry.id)
+    @infraspecies = build_taxon_concept(:rank =&gt; 'infraspecies', :depth =&gt; 4,
+                                        :parent_hierarchy_entry_id =&gt; @subspecies1.entry.id)
     @taxon_concept.children.map(&amp;:id).should only_include @subspecies1.id, @subspecies2.id, @subspecies3.id
   end
 </diff>
      <filename>spec/models/taxon_concept_spec.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>72231ee61a3be863dd1cdf697ad02ee107451754</id>
    </parent>
  </parents>
  <author>
    <name>jrice</name>
    <email>jrice@78829999-583a-0410-bd01-8a9b849fd409</email>
  </author>
  <url>http://github.com/eol/eol/commit/36e61f298e14ab9c105d8b65e381f7f8bf27ed5c</url>
  <id>36e61f298e14ab9c105d8b65e381f7f8bf27ed5c</id>
  <committed-date>2009-07-08T07:03:24-07:00</committed-date>
  <authored-date>2009-07-08T07:03:24-07:00</authored-date>
  <message>Various improvements to testing, including a few new tests needed before fixing 1122.

git-svn-id: file:///data/subversion/eol/trunk@826 78829999-583a-0410-bd01-8a9b849fd409</message>
  <tree>08897af5dfe3920c154d8d74d015030aa02f73cb</tree>
  <committer>
    <name>jrice</name>
    <email>jrice@78829999-583a-0410-bd01-8a9b849fd409</email>
  </committer>
</commit>
