【发布时间】:2017-10-26 08:45:30
【问题描述】:
我已经通过 Twilio 进行了电话号码验证,但我找不到如何实现再次发送 pin 码的功能(如果用户没有收到)但也不超过 3 次的方法(所以用户不能一遍又一遍地发送代码)。另外,我的代码看起来有点反模式,所以请随意提出更好的实现。
当设计用户注册自己时,我派他创建一个Profile 那个belongs_to 用户。 Profile 保存所有用户信息(和电话号码)。这是表格:
<%= form_for @profile, remote: true do |f| %>
<%= f.label 'Your name' %><br />
<%= f.text_field :first_name, autofocus: true, class: 'form-control' %>
<%= f.label 'Phone number' %><br />
<%= f.text_field :phone, class: 'form-control' %>
</br>
<div id="hideAfterSubmit">
<%= f.submit 'Save', class: 'btn btn-lg btn-primary btn-block' %>
</div>
<% end %>
<div id="verify-pin">
<h3>Enter your PIN</h3>
<%= form_tag profiles_verify_path, remote: true do |f| %>
<div class="form-group">
<%= text_field_tag :pin %>
</div>
<%= submit_tag "Verify PIN", class: "btn btn-primary" %>
<% end %>
</div>
<div id="status-box" class="alert alert-success">
<p id="status-message">Status: Haven’t done anything yet</p>
</div>
#verify-pin 和 #status-box 是 display: none。我通过回复create.js.erb 取消隐藏它们。
创建动作:
def create
if user_signed_in? && current_user.profile
redirect_to profile_path(current_user), notice: 'Jūs jau sukūrėte paskyrą'
else
@profile = Profile.new(profile_params)
@phone_number = params[:profile][:phone]
@profile.user_id = current_user.id
SmsTool.generate_pin
SmsTool.send_pin(phone_number: @phone_number)
if @profile.save
respond_to do |format|
format.js
end
else
render :new
end
end
end
因此,此时已创建、保存个人资料并生成 pin 码并将其发送到用户刚刚添加的电话号码。
短信工具:
def self.generate_pin
@@pin = rand(0000..9999).to_s.rjust(4, "0")
puts "#{@@pin}, Generated"
end
def self.send_pin(phone_number:)
@client.messages.create(
from: ENV['TWILIO_PHONE_NUMBER'],
to: "+370#{phone_number}",
body: "Your pin is #{@@pin}"
)
end
def self.verify(entered_pin)
puts "#{@@pin}, pin #{entered_pin} entered"
if @@pin == entered_pin
Current.user.profile.update(verified: true)
else
return
end
end
还有Profiles#verify:
def verify
SmsTool.verify(params[:pin])
@profile = current_user.profile
respond_to do |format|
format.js
end
if @profile.verified
redirect_to root_path, notice: 'Account created'
end
end
所以我不喜欢的是 SmsTool - 正如你所看到的,我使用类变量 - 找不到其他方法。我还创建了一个单独的 Current 模块,只是为了访问 Devise current_user object..:
module Current
thread_mattr_accessor :user
end
应用控制器:
around_action :set_current_user
def set_current_user
Current.user = current_user
yield
ensure
# to address the thread variable leak issues in Puma/Thin webserver
Current.user = nil
end
正如我上面提到的 - 我无法找到一种方法来实现再次发送 pin 码的功能(如果用户没有收到它)。
请 - 随意建议优雅的实现。
附言这是我最长的帖子了。很抱歉,但我认为需要所有信息才能向您展示。
更新:
所以重新发送 pin 很容易,我只是添加了:
<div id="hiddenUnlessWrongPin">
<%= button_to "Re-send pin", action: "send_pin_again" %>
</div>
和行动:
def send_pin_again
@phone_number = current_user.profile.phone
SmsTool.generate_pin
SmsTool.send_pin(phone_number: @phone_number)
end
但是如果用户已经发送了三个密码,我仍然不知道如何停止发送密码。我看到的唯一方法是在 db 中使用整数值创建新行,并在每次用户发送 pin 时增加它。这是唯一的方法吗?
【问题讨论】:
-
要重新发送 pin 我刚刚创建了一个单独的操作,但它太干了,看起来有点乱。所以仍然希望有好的实现。否则将在几个小时内删除
-
我发现的一件事是您在调用
@profile.save之前先调用SmsTool.send_pin(phone_number: @phone_number),这意味着即使记录无效也会发送密码。 -
哦,对了,谢谢@max。
标签: ruby-on-rails devise twilio ruby-on-rails-5