问题描述
|
我正在开发一个追逐/寻宝移动网络应用程序。我具有基本身份验证,如果用户扫描以下任何代码,则将其定向到sign_up页面。到目前为止,一切正常,但是棘手的部分出现了:
我有10个QR码,每一个都代表一个URL。
QR码ID:1 URL:http://paperchase.heroku.com/qrs/4975
QR码ID:2 URL:http://paperchase.heroku.com/qrs/2368
QR码ID:3 URL:http://paperchase.heroku.com/qrs/2317
QR码ID:4 URL:http://paperchase.heroku.com/qrs/2369
QR码ID:5 URL:http://paperchase.heroku.com/qrs/6247
QR码ID:6 URL:http://paperchase.heroku.com/qrs/1493
QR码ID:7 URL:http://paperchase.heroku.com/qrs/1759
QR码ID:8 URL:http://paperchase.heroku.com/qrs/4278
QR码ID:9 URL:http://paperchase.heroku.com/qrs/8912
QR码ID:10 URL:http://paperchase.heroku.com/qrs/5346
现在,我希望用户按所示顺序扫描每个代码。如果他扫描代码1,则将找到到代码2的路线;如果他扫描代码2,则将找到到代码3的路线,依此类推。但是现在可以跳过代码,例如您可以在代码1之后扫描代码10并赢。
我想出的解决方案:
所有QR码均设置为false。如果您扫描QR码1,它将被设置为true,并且可以扫描QR Code2。如果现在您想扫描QR Code 5,则由于QR Code 4被设置为false,它将重定向到root_path。
这是我的用户模型的一部分:
...
t.boolean :qr_01,:default => false
t.boolean :qr_02,:default => false
t.boolean :qr_03,:default => false
t.boolean :qr_04,:default => false
...
现在,我认为我必须用逻辑写一个“ 1”(将QR码设置为true,检查所有先前的QR码是否都设置为true),但是我不知道它的外观。
提前致谢
解决方法
为什么不只在模型中存储一个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
, 我认为您正在尝试将验证放在错误的位置,并且您的架构可能需要进行一些调整。
如果有人正在输入QR4,您是否真的关心他们已经通过QR3输入了QR1,还是真的只关心他们输入的最后一个是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
然后以通常的方式将该关联与您的User和QrCode模型关联起来。
还要注意,此结构只需要进行几个简单的修改即可允许同时运行多个“纸张追逐”。您只需要将几个模型从用户模型移至user_paper_chases
模型,并向to13ѭ添加一个paper_chase
参数即可。
没有规则说用户界面必须是数据模型属性的简单编辑器,并且将两者紧密地绑定在一起通常是一个错误(尽管这是一个非常常见的错误,但仍然是一个错误)。