使用范围验证值的唯一性 - Ruby on Rails 5

gdf*_*dfg 17 ruby-on-rails ruby-on-rails-3 ruby-on-rails-3.2 ruby-on-rails-4

我有posts一个带有模型的表和带有模型的Post表语言(列 - id、post_id、语言)Language。Post 有多种语言,Language 属于 Post。在后模型中,我有:

岗位型号:

has_many :languages
validates_associated :languages
Run Code Online (Sandbox Code Playgroud)

语言模型:

belongs_to :post
validates_uniqueness_of :language, scope: :post_id
Run Code Online (Sandbox Code Playgroud)

语言是表语言中的列。

post_controller 中允许使用语言字段(强参数):

def post_params
    params.require(:post).permit(:languages_attributes => [:language], ...)
Run Code Online (Sandbox Code Playgroud)

这是用于创建帖子的表单的视图:

<%= 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 %>
Run Code Online (Sandbox Code Playgroud)

这是创建帖子方法:

@post= Post.new(post_params)
if @post.save
....
Run Code Online (Sandbox Code Playgroud)

我想验证具有帖子范围(范围::post_id)的语言的唯一性,并且每个帖子只有1次英语作为示例。帖子可以有 1 种以上的语言,但可以使用不同的语言。

我尝试过validates_uniqueness_of :language, scope: :post_id,但是如果我添加两次英语(全部小写),则没有错误,并且数据会插入到表中。

如何在当前帖子的范围内验证帖子的语言的唯一性?

编辑:我看到这是 Rails - GitHub 中的一个错误,但我仍然需要一个解决方案。

Han*_*oh. 18

如何验证 Rails 5 中两列的唯一性?这是答案

validates :username, uniqueness: { scope: :group_id }
Run Code Online (Sandbox Code Playgroud)

如果您需要记录唯一,请为记录添加唯一索引

class AddUniqueIndexToRoles < ActiveRecord::Migration[5.2]
  def change
    add_index :roles, [:username, :group_id], unique: true
  end
end
Run Code Online (Sandbox Code Playgroud)


Gan*_*esh 5

我还没有完全理解你的问题,但如果你无法通过以下方式验证唯一性

validates_uniqueness_of :language, scope: :post_id
Run Code Online (Sandbox Code Playgroud)

那么你可以尝试像下面这样

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
Run Code Online (Sandbox Code Playgroud)

我希望这对你有用......