使用除非的Rails模型验证

时间:2015-01-07 08:07:10

标签: ruby-on-rails validation model proc

我有以下模型订阅类

create_table "subscriptions", force: true do |t|
    t.integer  "user_id"
    t.integer  "course_id"
    t.datetime "date_subscription_start"
    t.datetime "date_subscription_end"
    t.string   "subscription_type"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

我想这样做,以便用户可以再次订阅同一个类,如果他们出于某种原因想要重新购买它。我的逻辑是,如果在新创建时已经传递了类/用户组合的date_subscription_end日期,则应该只能注册一个类。如果在创建时存在具有相同user_id和course_id的订阅,其中将来具有subscription_end日期,则应拒绝该订阅,因为这意味着用户仍在使用该课程。

这样的事情:

validates :user_id,
  uniqueness: {
    scope: :course_id,
    message: "User is already subscribed to this course"
  },
  unless: Proc.new { |a|
   Subscription.where(user_id: a.user_id, course_id: a.course_id) &&
     Subscription.where('date_subscription_end < ?', Time.now)
  }

基本上,rails必须通过订阅表,查找具有相同主键的所有订阅,并检查其date_subscription_end属性。我觉得我很接近,却遗漏了一些基本的东西。

谢谢! 让

编辑:由于某种原因,&#34;你好!&#34;帖子顶部的问候语被删除

1 个答案:

答案 0 :(得分:0)

首先,Proc看起来不正确,只要用户订阅并且某些用户(不一定是a.user_id)订阅,我就会看到Proc返回真值任何课程(不一定是a.course_id

其次,除非需要是if并且是唯一性验证的选项哈希的一部分。

因此以下代码应该有效:

validates :user_id,
  uniqueness: {
    scope: :course_id,
    message: "User is already subscribed to this course",
    if: Proc.new { |a|
      Subscription.where(user_id: a.usr_id, course_id: a.course_id)
        .where('date_subscription_end >= ?', Time.now).exists?
    }
  }

这样,您只需访问一次数据库,而您的代码不需要实例化所有匹配的订阅,就像您只运行.where(…)

一样

<强>更新

date_subscription_end的条件应为:'date_subscription_end >= ?', Time.now