Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails database uniqueness validation not working

I am at a total loss with this one. I have a Rails application in which users may create a new vendor for use in the system. This vendor must have a unique name. As such we have a unique index on the database for this field as seen below:

create_table "vendors", force: :cascade do |t|
  t.string   "vendor_name", limit: 80, null: false
  t.datetime "updated_at",             null: false
end

add_index "vendors", ["vendor_name"], name: "vendor_name_UNIQUE", unique: true, using: :btree

My issue is that for some reason the Rails validation is not working with this, therefore the application is throwing an exception because the database query is failing. The exception is below:

ActiveRecord::RecordNotUnique in VendorsController#create

Mysql2::Error: Duplicate entry '3 logiq' for key 'vendor_name_UNIQUE': INSERT INTO `vendors` (`vendor_name`, `updated_at`) VALUES ('3 logiq', '2015-12-03 21:14:12')

My Rails validation in the vendor.rb model file is as follows:

validates :vendor_name, presence: true, uniqueness: true, length: { minimum: 5, maximum: 80 }

I know the validation is being run, because I still receive form errors for the length and presence checks. Unsure what I can do at this point. Have I missed something?

Below is my vendors controller code:

def create
  @vendor = Vendor.new(vendor_params)
  @vendor.comments.build(user_comment: comment_params[:new_comment], system_note: 'Created Vendor', user: current_user, user_agent: request.user_agent, resolution: comment_params[:screen_resolution])

  respond_to do |format|
    if @vendor.save
      format.html { redirect_to vendors_path, notice: 'Vendor was successfully created.' }
      format.json { render :show, status: :created, location: @vendor }
    else
      format.html { @new_item = true; render :new }
      format.json { render json: @vendor.errors, status: :unprocessable_entity }
    end
  end
end

Vendor form view code:

<% if @vendor.errors.any? %>
    <div>
      <div class="alert alert-danger" role="alert" id="error_explanation">
        <h4><strong><%= pluralize(@vendor.errors.count, "error") %></strong> prohibited this vendor from being saved:</h4>

        <ul>
          <% @vendor.errors.full_messages.each do |message| %>
              <li><%= message %></li>
          <% end %>
        </ul>
      </div>
    </div>
<% end %>
like image 552
SDee Avatar asked Sep 26 '22 01:09

SDee


1 Answers

The issue was in fact related to case sensitivity. The solution was to add a small bit to the validation line in the vendor model.

The previous validation line:

validates :vendor_name, presence: true, uniqueness: true, length: { minimum: 5, maximum: 80 }

Becomes:

validates :vendor_name, presence: true, uniqueness: { case_sensitive: false }, length: { minimum: 5, maximum: 80 }

Notice the difference in the uniqueness part. Rails does care about case sensitivity by default, therefore my validation was not being ran every single time in my case.

Hope this helps anyone else that comes across this!

like image 106
SDee Avatar answered Oct 04 '22 20:10

SDee