acts_as_textcaptcha 4.2.0 → 4.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +2 -1
- data/.rubocop.yml +1165 -0
- data/.simplecov +11 -0
- data/.travis.yml +30 -8
- data/Appraisals +9 -6
- data/CHANGELOG.md +94 -34
- data/CODE_OF_CONDUCT.md +54 -31
- data/CONTRIBUTING.md +14 -9
- data/Gemfile +2 -2
- data/LICENSE +165 -0
- data/PULL_REQUEST_TEMPLATE.md +16 -0
- data/README.md +206 -228
- data/Rakefile +26 -19
- data/acts_as_textcaptcha.gemspec +57 -41
- data/bin/console +2 -5
- data/bin/setup +7 -0
- data/gemfiles/rails_3.gemfile +1 -0
- data/gemfiles/rails_4.gemfile +2 -1
- data/gemfiles/rails_5.gemfile +2 -1
- data/gemfiles/rails_6.gemfile +8 -0
- data/lib/acts_as_textcaptcha.rb +9 -4
- data/lib/acts_as_textcaptcha/errors.rb +21 -0
- data/lib/acts_as_textcaptcha/framework/rails.rb +3 -1
- data/lib/acts_as_textcaptcha/railtie.rb +9 -0
- data/lib/acts_as_textcaptcha/tasks/textcaptcha.rake +17 -0
- data/lib/acts_as_textcaptcha/textcaptcha.rb +75 -72
- data/lib/acts_as_textcaptcha/textcaptcha_api.rb +39 -45
- data/lib/acts_as_textcaptcha/textcaptcha_cache.rb +12 -16
- data/lib/acts_as_textcaptcha/textcaptcha_config.rb +47 -0
- data/lib/acts_as_textcaptcha/textcaptcha_helper.rb +13 -14
- data/lib/acts_as_textcaptcha/version.rb +3 -1
- metadata +68 -46
- data/.coveralls.yml +0 -1
- data/LICENSE.txt +0 -21
- data/config/textcaptcha.yml +0 -34
- data/lib/tasks/textcaptcha.rake +0 -21
- data/test/schema.rb +0 -34
- data/test/test_helper.rb +0 -44
- data/test/test_models.rb +0 -69
- data/test/textcaptcha_api_test.rb +0 -46
- data/test/textcaptcha_cache_test.rb +0 -25
- data/test/textcaptcha_helper_test.rb +0 -68
- data/test/textcaptcha_test.rb +0 -198
@@ -0,0 +1,16 @@
|
|
1
|
+
|
2
|
+
Explain what you're changing and why here.
|
3
|
+
|
4
|
+
---
|
5
|
+
#### :memo: Checklist
|
6
|
+
|
7
|
+
Please check this list and leave it intact for the reviewer. Thanks! :heart:
|
8
|
+
|
9
|
+
- [ ] Commit messages provide context (why not just what, some tips [here](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html)).
|
10
|
+
- [ ] If relevant, mention GitHub issue number above and include in a commit message.
|
11
|
+
- [ ] Latest code from master merged.
|
12
|
+
- [ ] New behaviour has test coverage.
|
13
|
+
- [ ] Avoid duplicating code.
|
14
|
+
- [ ] No commented out code.
|
15
|
+
- [ ] Avoid comments for your code, write code that explains itself.
|
16
|
+
- [ ] Changes are simple, useful, clear and brief.
|
data/README.md
CHANGED
@@ -1,290 +1,268 @@
|
|
1
1
|
## ActAsTextcaptcha
|
2
2
|
|
3
|
-
[.
|
3
|
+
[](http://rubygems.org/gems/acts_as_textcaptcha)
|
4
|
+
[](https://travis-ci.com/matthutchinson/acts_as_textcaptcha)
|
5
|
+
[](https://depfu.com/github/matthutchinson/acts_as_textcaptcha)
|
6
|
+
[](https://codeclimate.com/github/matthutchinson/acts_as_textcaptcha/maintainability)
|
7
|
+
[](https://codeclimate.com/github/matthutchinson/acts_as_textcaptcha/test_coverage)
|
8
|
+
|
9
|
+
ActsAsTextcaptcha provides spam protection for Rails models with text-based
|
10
|
+
logic question captchas. Questions are fetched from [Rob
|
11
|
+
Tuley's](https://twitter.com/robtuley)
|
12
|
+
[textcaptcha.com](https://textcaptcha.com/). They can be solved easily by humans
|
13
|
+
but are tough for robots to crack.
|
14
|
+
|
15
|
+
The gem can also be configured with your own questions; as an alternative, or as
|
16
|
+
a fallback to handle any API issues. For reasons on why logic based captchas
|
17
|
+
are a good idea visit [textcaptcha.com](https://textcaptcha.com).
|
18
|
+
|
19
|
+
## Requirements
|
20
|
+
|
21
|
+
* [Ruby](http://ruby-lang.org/) >= 2.5
|
22
|
+
* [Rails](http://github.com/rails/rails) >= 4
|
23
|
+
* A valid [Rails.cache](http://guides.rubyonrails.org/caching_with_rails.html#cache-stores) (not `:null_store`)
|
25
24
|
|
26
25
|
## Demo
|
27
26
|
|
28
27
|
Try a [working demo here](https://acts-as-textcaptcha-demo.herokuapp.com)!
|
29
|
-
|
30
|
-
**Or** click below to deploy your own example Rails app to Heroku (already
|
31
|
-
configured with acts_as_textcaptcha). See
|
32
|
-
[here](https://github.com/matthutchinson/acts_as_textcaptcha_demo) for more
|
33
|
-
details.
|
28
|
+
Or one-click deploy your own [demo app](https://github.com/matthutchinson/acts_as_textcaptcha_demo) to Heroku.
|
34
29
|
|
35
30
|
[](https://www.heroku.com/deploy?template=https://github.com/matthutchinson/acts_as_textcaptcha_demo/tree/master)
|
36
31
|
|
37
|
-
##
|
32
|
+
## Installation
|
38
33
|
|
39
|
-
|
34
|
+
Add this line to your Gemfile and run `bundle install`:
|
40
35
|
|
41
|
-
|
36
|
+
```ruby
|
37
|
+
gem 'acts_as_textcaptcha'
|
38
|
+
```
|
42
39
|
|
43
|
-
Add
|
40
|
+
Add this to models you'd like to protect:
|
44
41
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
42
|
+
```ruby
|
43
|
+
class Comment < ApplicationRecord
|
44
|
+
acts_as_textcaptcha api_key: 'TEXTCAPTCHA_API_IDENTITY'
|
45
|
+
# see below for more config options
|
46
|
+
end
|
47
|
+
```
|
49
48
|
|
50
|
-
|
51
|
-
|
52
|
-
can be contacted
|
49
|
+
[Rob](https://twitter.com/robtuley) requests that your
|
50
|
+
`TEXTCAPTCHA_API_IDENTITY` be some reference to yourself (e.g. an email address,
|
51
|
+
domain or similar) so you can be contacted should any usage problem occur.
|
53
52
|
|
54
|
-
|
55
|
-
for the record, like so;
|
53
|
+
In your controller's `new` action call the `textcaptcha` method:
|
56
54
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
55
|
+
```ruby
|
56
|
+
def new
|
57
|
+
@comment = Comment.new
|
58
|
+
@comment.textcaptcha
|
59
|
+
end
|
60
|
+
```
|
61
61
|
|
62
|
-
|
63
|
-
|
64
|
-
block as you like;
|
62
|
+
Add the question and answer fields to your form using the
|
63
|
+
`textcaptcha_fields` helper. Arrange the HTML within this block as you like.
|
65
64
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
65
|
+
```ruby
|
66
|
+
<%= textcaptcha_fields(f) do %>
|
67
|
+
<div class="field">
|
68
|
+
<%= f.label :textcaptcha_answer, @comment.textcaptcha_question %><br/>
|
69
|
+
<%= f.text_field :textcaptcha_answer, :value => '' %>
|
70
|
+
</div>
|
71
|
+
<% end %>
|
72
|
+
```
|
72
73
|
|
73
|
-
|
74
|
-
|
74
|
+
If you'd prefer to construct your own form elements, take a look at the HTML
|
75
|
+
produced
|
75
76
|
[here](https://github.com/matthutchinson/acts_as_textcaptcha/blob/master/lib/acts_as_textcaptcha/textcaptcha_helper.rb).
|
76
77
|
|
77
|
-
|
78
|
-
|
79
|
-
changed with Rails 5 and this gem **requires** a working Rails.cache store to
|
80
|
-
exist.
|
78
|
+
Finally set a valid [cache
|
79
|
+
store](https://guides.rubyonrails.org/caching_with_rails.html#cache-stores) (not `:null_store`) for your environments:
|
81
80
|
|
82
|
-
|
83
|
-
|
84
|
-
|
81
|
+
```ruby
|
82
|
+
# e.g. in each config/environments/*.rb
|
83
|
+
config.cache_store = :memory_store
|
84
|
+
```
|
85
85
|
|
86
|
-
|
86
|
+
You can run `rails dev:cache` on a modern generated Rails app to enable
|
87
|
+
a memory store cache in the development environment.
|
87
88
|
|
88
|
-
|
89
|
-
`perform_textcaptcha?` method. If it returns false, no questions will be fetched
|
90
|
-
from the web service and captcha validation is disabled.
|
89
|
+
## Configuration
|
91
90
|
|
92
|
-
|
93
|
-
on/off e.g. for logged in users. By default the `perform_textcaptcha?` method
|
94
|
-
[checks if the object is a new (unsaved)
|
95
|
-
record](https://github.com/matthutchinson/acts_as_textcaptcha/blob/master/lib/acts_as_textcaptcha/textcaptcha.rb#L54).
|
91
|
+
The following options are available (only `api_key` is required):
|
96
92
|
|
97
|
-
|
98
|
-
|
99
|
-
|
93
|
+
* **api_key** (_required_) - a reference to yourself (e.g. your email or domain).
|
94
|
+
* **questions** (_optional_) - array of your own questions and answers (see below).
|
95
|
+
* **cache_expiry_minutes** (_optional_) - how long valid answers are cached for (default 10 minutes).
|
96
|
+
* **raise_errors** (_optional_) - if true, API or network errors are raised (default false, errors logged).
|
97
|
+
* **api_endpoint** (_optional_) - set your own JSON API endpoint to fetch from (see below).
|
100
98
|
|
101
|
-
|
102
|
-
acts_as_textcaptcha :api_key => 'TEXTCAPTCHA_API_IDENTITY'
|
99
|
+
For example:
|
103
100
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
101
|
+
```ruby
|
102
|
+
class Comment < ApplicationRecord
|
103
|
+
acts_as_textcaptcha api_key: 'TEXTCAPTCHA_API_IDENTITY_KEY',
|
104
|
+
raise_errors: false,
|
105
|
+
cache_expiry_minutes: 10,
|
106
|
+
questions: [
|
107
|
+
{ 'question' => '1+1', 'answers' => '2,two' },
|
108
|
+
{ 'question' => 'The green hat is what color?', 'answers' => 'green' }
|
109
|
+
]
|
110
|
+
end
|
111
|
+
```
|
108
112
|
|
109
|
-
###
|
113
|
+
### YAML config
|
110
114
|
|
111
|
-
You can
|
115
|
+
You can apply an app wide config with a `config/textcaptcha.yml` file. Use this
|
116
|
+
rake task to add one from a
|
117
|
+
[template](https://github.com/matthutchinson/acts_as_textcaptcha/blob/master/lib/acts_as_textcaptcha/textcaptcha_config.rb):
|
112
118
|
|
113
|
-
|
114
|
-
* *questions* (_optional_) - array of question and answer hashes (see below) A random question from this array will be asked if the web service fails OR if no `api_key` has been set. Multiple answers to the same question are comma separated (e.g. 2,two). Don't use commas in your answers!
|
115
|
-
* *cache_expiry_minutes* (_optional_) - minutes for answers to persist in the cache (default 10 minutes), see [below for details](https://github.com/matthutchinson/acts_as_textcaptcha#what-does-the-code-do)
|
116
|
-
* *http_read_timeout* (_optional_) - Net::HTTP option, seconds to wait for one block to be read from the remote API
|
117
|
-
* *http_open_timeout* (_optional_) - Net::HTTP option, seconds to wait for the connection to open to the remote API
|
119
|
+
$ bundle exec rake textcaptcha:config
|
118
120
|
|
119
|
-
|
121
|
+
**NOTE**: Any options set in models take preference over this config.
|
120
122
|
|
121
|
-
|
122
|
-
acts_as_textcaptcha :api_key => 'TEXTCAPTCHA_API_IDENTITY',
|
123
|
-
:http_read_timeout => 60,
|
124
|
-
:http_read_timeout => 10,
|
125
|
-
:cache_expiry_minutes => 10,
|
126
|
-
:questions => [{ 'question' => '1+1', 'answers' => '2,two' },
|
127
|
-
{ 'question' => 'The green hat is what color?', 'answers' => 'green' }]
|
128
|
-
end
|
123
|
+
### Config without the TextCaptcha service
|
129
124
|
|
130
|
-
|
125
|
+
To use __only__ your own logic questions, omit the `api_key` and set them in the
|
126
|
+
config (see above). Multiple answers to the same question must be comma
|
127
|
+
separated e.g. `2,two` (so do not include commas in answers).
|
131
128
|
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
129
|
+
You can optionally set your own `api_endpoint` to fetch questions and answers
|
130
|
+
from. The URL must respond with a JSON object like this:
|
131
|
+
|
132
|
+
```ruby
|
133
|
+
{
|
134
|
+
"q": "What number is 4th in the series 39, 11, 31 and nineteen?",
|
135
|
+
"a": ["1f0e3dad99908345f7439f8ffabdffc4","1d56cec552bf111de57687e4b5f8c795"]
|
136
|
+
}
|
137
|
+
```
|
138
|
+
|
139
|
+
With `"a"` being an array of answer strings, MD5'd, and lower-cased. The
|
140
|
+
`api_key` option is ignored if an `api_endpoint` is set.
|
141
|
+
|
142
|
+
### Toggling TextCaptcha
|
136
143
|
|
137
|
-
|
138
|
-
|
139
|
-
|
144
|
+
Enable or disable captchas by overriding the `perform_textcaptcha?` method (in
|
145
|
+
models). By default the method checks if the object is a new (unsaved) record.
|
146
|
+
So spam protection is __only__ enabled for creating new records (not updating).
|
140
147
|
|
141
|
-
|
148
|
+
Here's an example overriding the default behaviour but maintaining the new
|
149
|
+
record check.
|
142
150
|
|
143
|
-
|
151
|
+
```ruby
|
152
|
+
class Comment < ApplicationRecord
|
153
|
+
acts_as_textcaptcha :api_key => 'TEXTCAPTCHA_API_IDENTITY'
|
144
154
|
|
145
|
-
|
146
|
-
|
155
|
+
def perform_textcaptcha?
|
156
|
+
super && user.admin?
|
157
|
+
end
|
158
|
+
end
|
159
|
+
```
|
147
160
|
|
148
161
|
## Translations
|
149
162
|
|
150
|
-
The
|
151
|
-
English). Unfortunately at present, the TextCaptcha web service only provides
|
152
|
-
logic questions in English.
|
153
|
-
|
154
|
-
en:
|
155
|
-
activerecord:
|
156
|
-
errors:
|
157
|
-
models:
|
158
|
-
comment:
|
159
|
-
attributes:
|
160
|
-
textcaptcha_answer:
|
161
|
-
incorrect: "is incorrect, try another question instead"
|
162
|
-
expired: "was not submitted quickly enough, try another question instead"
|
163
|
-
activemodel:
|
164
|
-
attributes:
|
165
|
-
comment:
|
166
|
-
textcaptcha_answer: "TextCaptcha answer"
|
167
|
-
|
168
|
-
## Without ActiveRecord
|
169
|
-
|
170
|
-
It is possible to use this gem without ActiveRecord. As an example, take a look at the
|
171
|
-
[Contact](https://github.com/matthutchinson/acts_as_textcaptcha/blob/master/test/test_models.rb#L44)
|
172
|
-
model used in the test suite
|
173
|
-
[here](https://github.com/matthutchinson/acts_as_textcaptcha/blob/master/test/test_models.rb#L44).
|
174
|
-
|
175
|
-
## Testing and docs
|
176
|
-
|
177
|
-
In development you can run the tests and rdoc tasks like so;
|
178
|
-
|
179
|
-
* `rake test` (all tests)
|
180
|
-
* `rake test:coverage` (all tests with code coverage reporting)
|
181
|
-
* `appraisal rake test` (all tests with all gemfile variations)
|
182
|
-
* `appraisal rails-3 rake test` (all tests using a specific gemfile)
|
183
|
-
* `rake rdoc` (generate docs)
|
184
|
-
|
185
|
-
This gem uses [appraisal](https://github.com/thoughtbot/appraisal) to run the
|
186
|
-
test suite with multiple versions of Rails.
|
187
|
-
|
188
|
-
## What does the code do?
|
189
|
-
|
190
|
-
The gem contains two parts, a module for your ActiveRecord models, and a single
|
191
|
-
view helper method. The ActiveRecord module makes use of two futher classes,
|
192
|
-
[TextcaptchaApi](https://github.com/matthutchinson/acts_as_textcaptcha/blob/master/lib/acts_as_textcaptcha/textcaptcha_api.rb)
|
193
|
-
and
|
194
|
-
[TextcaptchaCache](https://github.com/matthutchinson/acts_as_textcaptcha/blob/master/lib/acts_as_textcaptcha/textcaptcha_cache.rb).
|
195
|
-
|
196
|
-
A call to `@model.textcaptcha` in your controller will query the TextCaptcha web
|
197
|
-
service. A GET request is made with Net::HTTP and parsed using the default Rails
|
198
|
-
`ActiveSupport::XMLMini` backend. A textcaptcha_question and a random cache key
|
199
|
-
are assigned to the record. An array of possible answers is also stored in the
|
200
|
-
TextcaptchaCache with this random key. The cached answers have (by default) a 10
|
201
|
-
minute TTL in your cache. If your forms take more than 10 minutes to be
|
202
|
-
completed you can adjust this value setting the `cache_expiry_minutes` option.
|
203
|
-
Internally TextcaptchaCache wraps
|
204
|
-
[Rails.cache](http://api.rubyonrails.org/classes/ActiveSupport/Cache/Store.html)
|
205
|
-
and all cache keys are name spaced.
|
206
|
-
|
207
|
-
On saving, `validate_textcaptcha` is called on @model.validate checking that the
|
208
|
-
`@model.textcaptcha_answer` matches one of the possible answers (retrieved from
|
209
|
-
the cache). By default, this validation is _only_ carried out on new records,
|
210
|
-
i.e. never on update, only on create. All attempted answers are case-insensitive
|
211
|
-
and have trailing/leading white-space removed.
|
212
|
-
|
213
|
-
Regardless of a correct, or incorrect answer the possible answers are cleared
|
214
|
-
from the cache and a new random key is generated and assigned. An incorrect
|
215
|
-
answer will cause a new question to be prompted. After one correct answer, the
|
216
|
-
answer and a mutating key are sent on further form requests, and no question is
|
217
|
-
presented in the form.
|
218
|
-
|
219
|
-
If an error or timeout occurs during API fetching, ActsAsTextcaptcha will fall
|
220
|
-
back to choose a random logic question defined in your options (see above). If
|
221
|
-
the web service fails or no API key is specified AND no alternate questions are
|
222
|
-
configured, the @model will not require textcaptcha checking and will pass as
|
223
|
-
valid.
|
224
|
-
|
225
|
-
For more details on the code please check the
|
226
|
-
[documentation](http://rdoc.info/projects/matthutchinson/acts_as_textcaptcha).
|
227
|
-
Tests are written with [MiniTest](https://rubygems.org/gems/minitest). Pull
|
228
|
-
requests and bug reports are welcome.
|
163
|
+
The following strings are translatable (with Rails I18n translations):
|
229
164
|
|
230
|
-
|
165
|
+
```yaml
|
166
|
+
en:
|
167
|
+
activerecord:
|
168
|
+
errors:
|
169
|
+
models:
|
170
|
+
comment:
|
171
|
+
attributes:
|
172
|
+
textcaptcha_answer:
|
173
|
+
incorrect: "is incorrect, try another question instead"
|
174
|
+
expired: "was not submitted quickly enough, try another question instead"
|
175
|
+
activemodel:
|
176
|
+
attributes:
|
177
|
+
comment:
|
178
|
+
textcaptcha_answer: "TextCaptcha answer"
|
179
|
+
```
|
180
|
+
|
181
|
+
**NOTE**: The textcaptcha.com API only provides logic questions in English.
|
182
|
+
|
183
|
+
## Handling Errors
|
184
|
+
|
185
|
+
The API may be unresponsive or return an unexpected response. If you've set
|
186
|
+
`raise_errors: true`, consider handling these errors:
|
187
|
+
|
188
|
+
* `ActsAsTextcaptcha::ResponseError`
|
189
|
+
* `ActsAsTextcaptcha::ParseError`
|
190
|
+
* `ActsAsTextcaptcha::ApiKeyError`
|
191
|
+
|
192
|
+
## Development
|
193
|
+
|
194
|
+
Check out this repo and run `bin/setup`, this will install gem dependencies and
|
195
|
+
generate docs. Use `bundle exec rake` to run tests and generate a coverage
|
196
|
+
report.
|
197
|
+
|
198
|
+
You can also run `bin/console` for an interactive prompt to experiment with the
|
199
|
+
code.
|
200
|
+
|
201
|
+
## Tests
|
231
202
|
|
232
|
-
|
203
|
+
MiniTest is used for testing. Run the test suite with:
|
233
204
|
|
234
|
-
|
235
|
-
* [Rails.cache](http://guides.rubyonrails.org/caching_with_rails.html#cache-stores) - a basic cache configuration is necessary
|
236
|
-
* [Ruby](http://ruby-lang.org/) >= 2.1
|
205
|
+
$ rake test
|
237
206
|
|
238
|
-
|
239
|
-
|
240
|
-
class directly wraps the
|
241
|
-
[Rails.cache](http://api.rubyonrails.org/classes/ActiveSupport/Cache/Store.html).
|
242
|
-
An alternative TextcaptchaCache implementation will be necessary if
|
243
|
-
`Rails.cache` is not available.
|
207
|
+
This gem uses [appraisal](https://github.com/thoughtbot/appraisal) to test
|
208
|
+
against multiple versions of Rails.
|
244
209
|
|
210
|
+
* `appraisal rake test` (run tests against all Gemfile variations)
|
211
|
+
* `appraisal rails-3 rake test` (run tests against a specific Gemfile)
|
245
212
|
|
246
|
-
##
|
213
|
+
## Docs
|
247
214
|
|
248
|
-
|
249
|
-
to continue to use this gem with an older version of Rails (>= 2.3.8), please
|
250
|
-
lock your Gemfile with version `4.0.0`. Like so;
|
215
|
+
Generate docs for this gem with:
|
251
216
|
|
252
|
-
|
253
|
-
gem 'acts_as_textcaptcha', '=4.0.0'
|
217
|
+
$ rake rdoc
|
254
218
|
|
255
|
-
|
256
|
-
config.gem 'acts_as_textcaptcha', :version => '=4.0.0'
|
219
|
+
## Troubles?
|
257
220
|
|
258
|
-
|
259
|
-
[
|
260
|
-
|
221
|
+
If you think something is broken or missing, please raise a new
|
222
|
+
[issue](https://github.com/matthutchinson/acts_as_textcaptcha/issues). Please
|
223
|
+
remember to check it hasn't already been raised.
|
224
|
+
|
225
|
+
## Contributing
|
226
|
+
|
227
|
+
Bug [reports](https://github.com/matthutchinson/acts_as_textcaptcha/issues) and
|
228
|
+
[pull requests](https://github.com/matthutchinson/acts_as_textcaptcha/pulls) are
|
229
|
+
welcome on GitHub. When submitting pull requests, remember to add tests covering
|
230
|
+
any new behaviour, and ensure all tests are passing on
|
231
|
+
[Travis](https://travis-ci.com/matthutchinson/acts_as_textcaptcha). Read the
|
232
|
+
[contributing
|
233
|
+
guidelines](https://github.com/matthutchinson/acts_as_textcaptcha/blob/master/CONTRIBUTING.md)
|
234
|
+
for more details.
|
235
|
+
|
236
|
+
This project is intended to be a safe, welcoming space for collaboration, and
|
237
|
+
contributors are expected to adhere to the [Contributor
|
238
|
+
Covenant](http://contributor-covenant.org) code of conduct. See
|
239
|
+
[here](https://github.com/matthutchinson/acts_as_textcaptcha/blob/master/CODE_OF_CONDUCT.md)
|
240
|
+
for more details.
|
241
|
+
|
242
|
+
## Todo
|
243
|
+
|
244
|
+
* Allow translatable user supplied questions and answers in config
|
245
|
+
* Allow `Net::HTTP` to be swapped out for any another HTTP client.
|
246
|
+
|
247
|
+
## License
|
248
|
+
|
249
|
+
The code is available as open source under the terms of
|
250
|
+
[LGPL-3](https://opensource.org/licenses/LGPL-3.0).
|
251
|
+
|
252
|
+
## Who's who?
|
253
|
+
|
254
|
+
* [ActsAsTextcaptcha](http://github.com/matthutchinson/acts_as_textcaptcha) and [little robot drawing](http://www.flickr.com/photos/hiddenloop/4541195635/) by [Matthew Hutchinson](http://matthewhutchinson.net)
|
255
|
+
* [TextCaptcha](https://textcaptcha.com) API and service by [Rob Tuley](https://twitter.com/robtuley)
|
261
256
|
|
262
257
|
## Links
|
263
258
|
|
264
259
|
* [Demo](https://acts-as-textcaptcha-demo.herokuapp.com)
|
265
|
-
* [Travis CI](http://travis-ci.
|
266
|
-
* [
|
267
|
-
* [
|
260
|
+
* [Travis CI](http://travis-ci.com/matthutchinson/acts_as_textcaptcha)
|
261
|
+
* [Maintainability](https://codeclimate.com/github/matthutchinson/acts_as_textcaptcha/maintainability)
|
262
|
+
* [Test Coverage](https://codeclimate.com/github/matthutchinson/acts_as_textcaptcha/test_coverage)
|
268
263
|
* [RDoc](http://rdoc.info/projects/matthutchinson/acts_as_textcaptcha)
|
269
264
|
* [Wiki](http://wiki.github.com/matthutchinson/acts_as_textcaptcha/)
|
270
265
|
* [Issues](http://github.com/matthutchinson/acts_as_textcaptcha/issues)
|
271
266
|
* [Report a bug](http://github.com/matthutchinson/acts_as_textcaptcha/issues/new)
|
272
267
|
* [Gem](http://rubygems.org/gems/acts_as_textcaptcha)
|
273
268
|
* [GitHub](http://github.com/matthutchinson/acts_as_textcaptcha)
|
274
|
-
|
275
|
-
## Who's who?
|
276
|
-
|
277
|
-
* [ActsAsTextcaptcha](http://github.com/matthutchinson/acts_as_textcaptcha) and [little robot drawing](http://www.flickr.com/photos/hiddenloop/4541195635/) by [Matthew Hutchinson](http://matthewhutchinson.net)
|
278
|
-
* [TextCaptcha](http://textcaptcha.com) API and service by [Rob Tuley](https://twitter.com/robtuley)
|
279
|
-
|
280
|
-
## Usage
|
281
|
-
|
282
|
-
This gem is used in a number of production websites and apps. It was originally
|
283
|
-
extracted from code developed for [Bugle](http://bugleblogs.com). If you're
|
284
|
-
happily using acts_as_textcaptcha in production, please let me know and I'll add
|
285
|
-
you to this list!
|
286
|
-
|
287
|
-
* [matthewhutchinson.net](http://matthewhutchinson.net)
|
288
|
-
* [pmFAQtory.com](http://pmfaqtory.com)
|
289
|
-
* [The FAQtory](http://faqtoryapp.com)
|
290
|
-
* [DPT Watch, San Francisco](http://www.dptwatch.com)
|