22

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.

gdfgdfg
  • 3,181
  • 7
  • 37
  • 83
  • 1
    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 – Pranav Singhal Jan 15 '18 at 18:51
  • it is called `language`. – gdfgdfg Jan 15 '18 at 19:21
  • Does this answer your question? [Validate uniqueness of multiple columns](https://stackoverflow.com/questions/4870961/validate-uniqueness-of-multiple-columns) – potashin Oct 22 '21 at 08:46

2 Answers2

30

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
Hany Moh.
  • 949
  • 1
  • 11
  • 11
9

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

validate :unique_language_id


def unique_language_id
  if post.languages.where(language: self.language).exist?
    error.add(:language_id, :taken)
  end
end

I hope this will work for you...

Ryan Taylor
  • 12,559
  • 2
  • 39
  • 34
Ganesh
  • 1,924
  • 1
  • 18
  • 31
  • `*** NoMethodError Exception: undefined method `languages' for # ` 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 Jan 15 '18 at 20:16
  • 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. – gdfgdfg Jan 15 '18 at 20:18