2015-10-26 55 views
0

我在有必须一组由表中指定的术语相匹配的字符串字段Rails的几个表,CvTerm(简称controlled_vocabulary)。 CvTerm作为一个特定于表和字段的白名单;例如,表Foo可能有一个字段Bar,其中唯一允许的条目是Baz,BaxQuux,对于该字段,将为每个允许的条目创建CvTerms。DRY的方式来纠正相同的验证领域

我写了一个自定义验证,以确保用户分配给这些字段的值相匹配的为表设置的一个;这个验证器可以在所有模型中用作单线程,validates :field, is_controlled: true

class IsControlledValidator < ActiveModel::EachValidator 
    def validate_each(record, attribute, value) 
     if options[:has_context] 
      allowed_terms = CvTerm.where({ 
       :related_table => record.class.to_s, 
       :related_field => attribute.to_s, 
       :context_table => record.related_type 
      }).map(&:term) 
     else 
      allowed_terms = CvTerm.where(:related_table => record.class.to_s, :related_field => attribute.to_s).map(&:term) 
     end 
     unless allowed_terms.include?(value) 
      record.errors[attribute] << "must be included in the allowed terms:\n#{allowed_terms.join("\n")}" 
     end 
    end 
end 

这是在我的模型,以实现方便,如预期运作近,但它是区分大小写的:这将是很烦人的强制用户手动确保的情况是完全一样的初始输入允许术语。

除了把这种情况下,修正的验证,我的理解是不可取的,是有办法做到这一点并不需要我单独情况下,正确的每一个控制领域?

回答

0

我会做两件事情。

  1. 使用pluck代替映射,它在sql上更快,而且您不必循环以获取该术语。

  2. 而不是做直哪里相似或ILIKE(MySQL的Postgres的VS),以去除大小写

  3. (也许)移动搜索成一个查询对象。

+0

这些都是很好的性能指针,虽然受控词汇表通常足够小,以至于任何性能命中都可以忽略不计。我更关心的是数据一致性 - 我怎样才能让我的用户以均匀的长期风,而不必以确保每一个最后的大写字母被妥善安置? – Vardarac

+0

听起来好像你需要在保存前在后端进行这种转换。这是您确保它采用特定格式的唯一方法。你也可以用postgres中的ilike做一个不区分大小写的搜索。 – Austio