我有3个型号:
class UserLanguage < ActiveRecord::Base
belongs_to :user
belongs_to :language
end
class Language < ActiveRecord::Base
has_many :user_languages
has_many :users, :through => :user_languages
end
class User < ActiveRecord::Base
has_many :user_languages, :dependent => :destroy
has_many :languages, :through => :user_languages
accepts_nested_attributes_for :user_languages, :allow_destroy => true
end
我正在使用nested_form gem来帮助用户选择他们可以说的语言。对此的CRUD工作正常。
但是,我无法验证UserLanguage的唯一性。我尝试了这两种语法,但它们对我不起作用:
validates_uniqueness_of :language_id, scope: :user_id
validates :language_id, :uniqueness => {:scope => user_id}
我的user_languages表架构:
create_table "user_languages", force: :cascade do |t|
t.integer "user_id"
t.integer "language_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "user_languages", ["language_id"], name: "index_user_languages_on_language_id", using: :btree
add_index "user_languages", ["user_id"], name: "index_user_languages_on_user_id", using: :btree
我应该怎样做以确保一个用户只能选择一种语言?比如,如果我在下拉列表中选择英语,我的第二个英语将不会被保存(重复)并被拒绝。
答案 0 :(得分:0)
如果用户已经且应该只有一种语言,那么您可以更改模型之间的基数:
class Language < ActiveRecord::Base
has_many :users
end
class User < ActiveRecord::Base
has_one :language
end
然后根据定义,您的用户一次只能使用一种语言,您的整体模型会更简单。
您可以阅读有关有效记录关联和基数的更多信息in this Association Basics guide
答案 1 :(得分:0)
这就是我最终做到的:
class UserLanguage < ActiveRecord::Base
belongs_to :user
belongs_to :language
def self.delete_duplicated_user_languages(user_id)
user_languages_ids = UserLanguage.where(user_id: user_id).pluck(:language_id).sort
duplicate_language_ids = user_languages_ids.select {|language| user_languages_ids.count(language) > 1}
duplicate_language_ids.uniq!
keep_this_language = []
duplicate_language_ids.each do |language_id|
keep_this_language << UserLanguage.find_by(user_id: user_id, language_id: language_id).id
end
single_language = user_languages_ids.select {|language| user_languages_ids.count(language) == 1}
single_language.each do |language|
keep_this_language << UserLanguage.find_by(user_id: user_id, language_id: language).id
end
UserLanguage.where(user_id: user_id).where.not(id: keep_this_language).destroy_all
end
end
我首先保存所有UserLanguage
并稍后删除它们(重复的)。