I can think of doing that in two ways:
The first one is based on failed_attempts attribute (so you should increment it after each unsuccesful login). To use it on Devise, you may create your own FailureApp
overriding the respond method to update to do an increment on the failed_attempt attribute on the user. When the user reaches the captcha limit, you may set a the flash attribute to signalize about this and thus, you decide on your controller about the captcha. But there is a problem with this way: as it logs for users, it won't work for an user trying different logins.
The second one is based on the IP: for each unsuccessful login, you keep record of IPs and unsuccessful attempts and when an IP reaches a limit you set the already mentioned flash attribute to signalize that the request number from that IP have already reached the limit and you can show the captcha. You can use ActiveRecord and a relational database or even something lightweight like Redis to do that. You may also think about ways to remove old data from this database.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…