Validate uniqueness of a value with scope - Ruby on Rails 5

21,617

Solution 1

How to validate the uniqueness of two columns in Rails 5? this is answer

validates :username, uniqueness: { scope: :group_id }

if you need records to be unique, add a unique index to records

class AddUniqueIndexToRoles < ActiveRecord::Migration[5.2]
  def change
    add_index :roles, [:username, :group_id], unique: true
  end
end

Solution 2

I have not understood your question completely, but if you are unable to validate uniqueness with following

validates_uniqueness_of :language, scope: :post_id

then you can try something like below

validates :validate_language_id


def validate_language_id
  if post.languages.where(language: self.language).exist?
     error.add(:language_id, 'has already been taken')
  end
end

I hope this will work for you...

Share:
21,617

Related videos on Youtube

gdfgdfg
Author by

gdfgdfg

Updated on July 09, 2022

Comments

  • gdfgdfg
    gdfgdfg almost 2 years

    I have table posts with a model Post and table languages (columns - id, post_id, language) with a model Language. Post has many languages and Language belongs to a Post. In the post model I have:

    Post model:

    has_many :languages
    validates_associated :languages
    

    Language model:

    belongs_to :post
    validates_uniqueness_of :language, scope: :post_id
    

    language is the column in the table languages.

    The language field is allowed in the posts_controller (strong parameters):

    def post_params
        params.require(:post).permit(:languages_attributes => [:language], ...)
    

    This is the view for the form for creating a post:

    <%= form_for @post do |f| %>
        .....
        <%= f.fields_for :languages do |language| %>
            <%=language.select :language, ['english', 'italian', 'french', 'spanish'], name: 'post[languages_attributes][][language]' %>
            <%=language.select :language, ['english', 'italian', 'french', 'spanish'], name: 'post[languages_attributes][][language]' %>
            <%=language.select :language, ['english', 'italian', 'french', 'spanish'], name: 'post[languages_attributes][][language]' %>
            <%=language.select :language, ['english', 'italian', 'french', 'spanish'], name: 'post[languages_attributes][][language]' %>
        <% end %>
    

    This is create post method:

    @post= Post.new(post_params)
    if @post.save
    ....
    

    I want to validate uniqueness of the languages with scope of the post (scope: :post_id) and every post to have only 1 time English language for the example. The post can have more than 1 languages, but different languages.

    I tried with validates_uniqueness_of :language, scope: :post_id, but if I add two times English (all lowercase), there is no error for this and the data is inserted to the tables.

    How to validate uniqueness of the languages for a post with the scope of the current post ?

    EDIT: I see that this is a bug in Rails - GitHub, but I still need a solution.

    • Pranav Singhal
      Pranav Singhal over 6 years
      please tell which column in the languages table do u want to validate the uniqueness of in your language model. I don't think it is called language
    • gdfgdfg
      gdfgdfg over 6 years
      it is called language.
    • potashin
      potashin over 2 years
      Does this answer your question? Validate uniqueness of multiple columns
  • gdfgdfg
    gdfgdfg over 6 years
    *** NoMethodError Exception: undefined method languages' for #<Class:0x12fb4c78> ` and it must be validate not validates and Post. But I think even if this works it will select values from database, but there is no saved data before validations for this post (scope). I have parent model Post and child Language. I want for each posts to have only unique languages.
  • gdfgdfg
    gdfgdfg over 6 years
    Because of this scope Post (scope: :post_id). There can be duplicate values for the column language in languages table, but not duplicate for specific post.