0

I have a ruby function that creates a discourse topic if the title is not found.

def get_topic(user,title,created_at,bumped_at,last_posted_at,excerpt)


  title = title.gsub(/  /,' ')
  puts "get_topic.title:'#{title}' user.id:#{user.id} created_at:#{created_at} last_posted_at:#{last_posted_at} excerpt:#{excerpt}"
  result = Topic.find_by_title(title)
  if result == nil then
    result = Topic.create
    result.title = title
    result.fancy_title = title
    result.user_id = user.id
    result.last_post_user_id = user.id
    result.updated_at = last_posted_at
    result.created_at = created_at
    result.bumped_at = bumped_at
    result.last_posted_at = last_posted_at
    result.excerpt = excerpt
    result.save!
  else 
      puts result
      puts created_at,bumped_at,last_posted_at
      if result.user_id != user.id then
        result.user_id = user.id
        result.last_post_user_id = user.id
      end
      if result.updated_at != last_posted_at then
        result.updated_at = last_posted_at
      end
      if result.created_at != created_at then
        result.created_at = created_at
      end
      if result.bumped_at != bumped_at then
        result.bumped_at = bumped_at
      end
      if result.last_posted_at != last_posted_at then
        result.last_posted_at = last_posted_at
      end
      if result.excerpt != excerpt then
        result.excerpt = excerpt
      end
      if result.changed.length > 0 then
        result.save!
        puts result.slug
        post = result.first_post
        post.created_at = created_at
        post.updated_at = result.updated_at
        post.baked_at = result.bumped_at
        post.last_version_at = result.last_posted_at
        post.user_id = result.user_id
        post.last_editor_id = result.user_id
        post.raw = result.excerpt
        post.save!
        puts post
        #puts user.id
      end
  end 
  puts "get_topic.result.slug:#{result.slug}"
  return result
end

Before the code creates a topic it searches for the title. title = title.gsub(/ /,' ') result = Topic.find_by_title(title) If a nil result occurs it then creates a topic.

It works for most topics, however, for one title it’s throwing ActiveRecord::RecordInvalid: Validation failed: Title has already been used when the topic is being saved.

The valiation settings for topic.title is

validates :title, if: Proc.new { |t| t.new_record? || t.title_changed? }, presence: true, topic_title_length: true, censored_words: true, quality_title: { unless: :private_message? }, max_emojis: true, unique_among: { unless: Proc.new { |t| (SiteSetting.allow_duplicate_topic_titles? || t.private_message?) }, message: :has_already_been_used, allow_blank: true, case_sensitive: false, collection: Proc.new { Topic.listable_topics } } I’ve checked in the console using Topic.find_by_title(‘title’). No topics exist with the title. I checked using Topic.find_by_sql("select * from topics where title like ‘start of title%’). No topics exist with the first word of the title.

What other checks can done … what could be causing the error saying the topic title has already been used when there are no topics found with that title?

Further information

I tried turning on allowing duplicate titles. The code ran through without an error yet there were no topics with the title that was causing the error after the import. Feels like the error message is wrong.

Keith John Hutchison
  • 4,955
  • 11
  • 46
  • 64
  • Is the validation in the Topic class custom or simply `uniqueness: true`? Could you have titles in your DB that are equivalent to your search term after stripping whitespace, but not before? – rwold Jan 02 '19 at 23:31
  • The validation is custom. Adding to question. The process of saving a Topic instance removes whitespace, including double spaces within the title. – Keith John Hutchison Jan 02 '19 at 23:37
  • I'm not familiar with `unique_among`, is that a custom validation? Some of your others appear to be. If so, please provide the code for that too. – rwold Jan 03 '19 at 00:11
  • I'm not yet familiar with unique_among either. I'm running an open source discourse server. It feels like the error message is somehow wrong. – Keith John Hutchison Jan 03 '19 at 00:24
  • 1
    Does the title you're checking contain any single or double quotes, or special characters? Can you share the title you're validating against? Also, is `find_by_title` just the older syntax (e.g. equivalent to `Topic.find_by(title: title)`, or is it a custom method on your `Title` model? – Jay Dorsey Jan 03 '19 at 02:37
  • 1
    @JayDorsey Discovered it was a case issue after a lead from Jay Pfaffman on meta.discourse.com. The title started with a lower case letter. When it was saved it the first letter was upper case. – Keith John Hutchison Jan 03 '19 at 02:54
  • @JayDorsey So the resolution would be to do a case-insensitive search. – Keith John Hutchison Jan 03 '19 at 02:58

0 Answers0