2011-06-14 3 views
1

Я работаю над бумажной сукой или поиском сокровищ мобильного веб-приложения. У меня есть базовая аутентификация, если пользователь сканирует любой из следующих кодов, он будет перенаправлен на страницу sign_up. Пока все работает нормально, но здесь идет сложная часть:Rails 3 before_filter настройка и проверка булевых значений | paperchase/treasure hunt game

У меня есть 10 QR-кодов, каждый из которых представляет один URL-адрес.

  1. QR-код ID: 1 URL: HTTP: //paperchase.heroku.com/qrs/4975
  2. QR-код ID: 2 URL: HTTP: //paperchase.heroku.com/qrs/ 2368
  3. QR-код ID: 3 URL: HTTP: //paperchase.heroku.com/qrs/2317
  4. QR-код ID: 4 URL: HTTP: //paperchase.heroku.com/qrs/2369
  5. QR-код ID: 5 URL: HTTP: //paperchase.heroku.com/qrs/6247
  6. QR-код ID: 6 URL: HTTP: //paperchase.heroku.com/qrs/1493
  7. QR-код ID: 7 URL: HTTP: //paperchase.heroku.com/qrs/1759
  8. QR-код ID: 8 URL: HTTP: //paperchase.heroku.com/qrs/4278
  9. QR -кода ID: 9 URL: HTTP: //paperchase.heroku.com/qrs/8912
  10. QR-код ID: 10 URL: HTTP: //paperchase.heroku.com/qrs/5346

Теперь я хочу, чтобы пользователь сканировал каждый отдельный код в указанном порядке. Если он сканирует код 1, он найдет указания для кода 2, если он сканирует код 2, он найдет указания для кода 3 и так далее. Но сейчас можно пропустить коды, например. вы можете сканировать код 10 после кода 1 и выиграть.

Решение, которое я придумал:

Все QR-коды установлены на ложь. Если вы сканируете QR-код 1, он будет установлен в true, и вы можете сканировать QR-код 2. Если вы сейчас хотите отсканировать QR-код 5, он перенаправляет вас на root_path, потому что QR-Code 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 
    ... 

Теперь я думаю, что я должен написать какую-то before_filter с логикой (настройка QR-кодов, правда, проверяя, если все предыдущие QR-кодов установлены в true). Но я понятия не имею, как это должно выглядеть.

Заранее спасибо

ответ

0

Почему бы не просто сохранить одно поле 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 
+0

thx, это приятное и простое решение! –

0

Я думаю, что вы пытаетесь поставить проверку в неправильном месте, и ваша схема может использовать немного настройки.

Если кто-то вводит 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-Code) пар имеет смысл для целей аудита, но было бы больше смысла для меня, чтобы иметь отдельную модель (как объединение таблица):

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 обычным способом.

Также обратите внимание, что для этой структуры потребуется лишь несколько простых модификаций, позволяющих одновременно запускать несколько «бумажных чеков». Вам просто нужно переместить пару вещей из вашей модели пользователя в модель user_paper_chases и добавить параметр paper_chase в User#add_code.

Нет правила, в котором говорится, что ваш пользовательский интерфейс должен быть простым редактором для ваших свойств модели данных и плотно связывать их, как это часто бывает ошибкой (невероятно распространенная ошибка, но ошибка, тем не менее).

+0

Thx за подробный ответ. На данный момент у меня все работает с идеей @ Msencenb. Я буду копаться в вашем подходе, пытаясь улучшить мой код как можно скорее. –