Ruby Rails 3前过滤器设置和检查布尔值| paperchase/寻宝游戏

Ruby Rails 3前过滤器设置和检查布尔值| paperchase/寻宝游戏,ruby,ruby-on-rails-3,qr-code,before-filter,Ruby,Ruby On Rails 3,Qr Code,Before Filter,我正在开发paperchase/寻宝手机网络应用程序。我有基本的身份验证,如果用户扫描以下任何代码,他将被引导到注册页面。到目前为止,一切正常,但棘手的是: 我有10个二维码,每个二维码代表一个URL 二维码ID:1 URL:http://paperchase.heroku.com/qrs/4975 二维码ID:2 URL:http://paperchase.heroku.com/qrs/2368 二维码ID:3 URL:http://paperchase.heroku.com/qrs/2317

我正在开发paperchase/寻宝手机网络应用程序。我有基本的身份验证,如果用户扫描以下任何代码,他将被引导到注册页面。到目前为止,一切正常,但棘手的是:

我有10个二维码,每个二维码代表一个URL

二维码ID:1 URL:http://paperchase.heroku.com/qrs/4975 二维码ID:2 URL:http://paperchase.heroku.com/qrs/2368 二维码ID:3 URL:http://paperchase.heroku.com/qrs/2317 二维码ID:4 URL:http://paperchase.heroku.com/qrs/2369 二维码ID:5 URL:http://paperchase.heroku.com/qrs/6247 二维码ID:6 URL:http://paperchase.heroku.com/qrs/1493 二维码ID:7 URL:http://paperchase.heroku.com/qrs/1759 二维码ID:8 URL:http://paperchase.heroku.com/qrs/4278 二维码ID:9 URL:http://paperchase.heroku.com/qrs/8912 二维码ID:10 URL:http://paperchase.heroku.com/qrs/5346 现在,我希望用户按照显示的顺序扫描每一个代码。如果他扫描代码1,他会找到代码2的方向,如果他扫描代码2,他会找到代码3的方向,依此类推。但现在可以跳过代码,例如,您可以在代码1之后扫描代码10并获胜

我提出的解决方案是:

所有二维码都设置为false。如果您扫描二维码1,它将设置为true,您可以扫描二维码2。如果您现在想扫描QR代码5,它会将您重定向到根路径,因为QR代码4设置为false

这是我的用户模型的一部分:

  ...
  t.boolean :qr_01, :default => false
  t.boolean :qr_02, :default => false
  t.boolean :qr_03, :default => false
  t.boolean :qr_04, :default => false
  ...
现在,我想我必须编写某种前置过滤器,逻辑设置QR码为true,检查所有先前的QR码是否都设置为true,但我不知道它应该是什么样子


提前感谢

我认为您试图将验证放在错误的位置,您的模式可能需要一些调整

如果有人输入QR4,你真的关心他们已经输入了QR1到QR3,还是你真的只关心他们输入的最后一个是QR3?在输入新代码的那一刻,真正重要的是它紧跟在最后一个代码之后;而且,为了使事情保持一致,您可以使用虚拟QR0来表示尚未进入的状态

在您的用户模型中,您可以使用如下方法:

def add_code(qr)
    # Check that qr immediately follows self.last_qr;
    # if it does, then update and save things and
    # continue on; if it doesn't, then raise an
    # exception that says, more or less, "QR Code out
    # of sequence".
end
您可以跟踪用户模型中的上一个和当前代码,并使用验证挂钩确保它们正常:

before_create :initialize_qrs
validate :contiguous_qrs

#...

def initialize_qrs
  self.last_qr   = 0
  self.latest_qr = 0
end

def contiguous_qrs
  if(self.last_qr == 0 && self.latest_qr == 0)
    # New user, no worries.
    true
  elsif(self.latest_qr != self.last_qr + 1)
    # Sequence error, your `add_code` method should
    # prevent this from ever happening but, hey, bugs
    # happen and your code shouldn't trust itself any
    # more than it has to.
    false
  end
  true
end
您的add_code方法将在执行其他工作时设置self.last_qr和self.latest_qr

然后,在控制器中:

def enter_code
    # Get the code and validate it, leave it in qr
    begin
      current_user.add_code(qr)
    rescue Exception => e
      # Complain and wag your finger at them for cheating
    end
    # Give them instructions for finding the next one,
    # these instructions would, presumably, come from
    # something like "instructions = qr.next_one.instructions".
end
跟踪用户,QR码对对于审计目的来说是有意义的,但对于我来说,使用单独的模型作为关联表更有意义:

create table "user_qr_codes" do |t|
  t.datetime "created_at", :null => false
  t.datetime "updated_at", :null => false
  t.integer  "user_id",    :null => false
  t.integer  "qr_code_id", :null => false
end
然后以通常的方式将这种关联与您的用户和QrCode模型联系起来

还请注意,此结构只需进行几个简单的修改,即可同时运行多个纸张追逐。您只需要将一些东西从您的用户模型移动到一个用户-纸张-追逐模型,并将一个纸张-追逐参数添加到用户-添加-代码


没有规则规定用户界面必须是数据模型属性的简单编辑器,而将两者紧密绑定通常是一个错误—一个非常常见的错误,但仍然是一个错误。

为什么不在模型中只存储一个int字段

例如,如果我的用户模型

 t.integer :qr_code
您只需检查控制器内部的操作:

def add_qr
  user = User.find_by_id(params[:id])
  if user.qr_code != params[:qr_code]-1
    redirect_to(some_url)
  else
    user.qr_code+=1
    user.save
    #do whatever else you need to do and display view
  end
end

谢谢你的详细回答。现在,我已经按照@Msencenb的想法运行了所有的程序。我将深入研究您的方法,并尽快改进我的代码。