I've tried a handful of captchas for Rails 3 and none tend to play nicely with Mongoid. I don't need anything too fancy just something to do a quick human check.
How do you guys get one working with Mongoid? Are there alternative solutions?
That's outside mongoid scope, but still applicable. Have a look at Negative Captcha:
Negative captchas create a form that has tasks that only bots can perform, but humans cannot. This has the exact same effect, with (anecdotally) a much lower false positive identification rate when compared with positive captchas. All of this comes without making humans go through any extra trouble to submit the form. It really is win-win.
You can use simple-captcha v1rtual's branch with mongo support. Simple and clean setup and usage:
Just add to your Gemfile as:
gem 'wolcanus-simple_captcha', :require => 'simple_captcha', :git => 'git://github.com/v1rtual/simple-captcha.git'
Run generator:
rails generate simple_captcha
For Controller Based, add the following line in the file "app/controllers/application.rb":
ApplicationController < ActionController::Base
include SimpleCaptcha::ControllerHelpers
end
In the view file within the form tags add this code:
<%= show_simple_captcha %>
and in the controller’s action authenticate it as
if simple_captcha_valid?
do this
else
do that
end
See the branch for more options: https://github.com/v1rtual/simple-captcha
Related
In Rails 7, Turbolinks is replaced by Hotwire / Turbo. This patches up web links so that they become AJAX-style requests just like Turbolinks did, but also patches up forms. On the whole, we found this broke swathes of our application.
Forms that already had some kind of JS behaviour attached conflicted.
Standard Rails error handling idioms - "set the flash and render :new/render :edit" - break, astonishingly; one must add status: :unprocessable_entity and cross fingers.
If the controller handling a form submission redirects to a URL that includes a patch anchor (...#foo), Turbo strips it.
In the end, there's only so much data: {turbo: false} it makes sense to scatter all over your code base. Worse, we're using SimpleForm, so this becomes the even-more-cumbersome html: {data: {turbo: false}}.
Is there a way to _globally disable Turbo just for forms (ideally all forms, whatever their origin - just leave the <form> tag and everything inside it completely alone please) but leave the rest of its behaviour unchanged?
I posted this Q&A on Stack Overflow as I couldn't find any other solutions out there. Clearly, there are numerous shortcomings and I would much prefer to see a simple configuration flag for Turbo that would make it ignore forms - this would be an overwhelmingly preferable approach.
I still don't have a full solution either way, because forms generated internally by Rails for e.g. a link_to(...method: delete) are still a problem, but I did work around some of it using some monkey patching.
On the one hand there are Rails forms:
Apparently, a data-turbo attribute's value apples to that node and all children so one can wrap e.g. a Rails-generated 'dynamic' form from e.g. a link_to(...method: delete) in a DIV with that attribute set and, at least, work around those problems on a case-by-case basis - though note, I'm having trouble making this work in some cases still.
If you have a lot of these, though, that's going to be intrusive and ugly, so it'd still be nice to have a way to have Turbo just ignore forms completely.
On the other hand there are SimpleForm forms:
SimpleForm provides no way to globally configure data attributes that will be added to form elements that it constructs. Previous requests for this in GitHub issues have so far been explicitly refused.
SimpleForm appears to provide no way to configure a wrapper that would go around the form as a whole, only custom wrappers for inputs within a form. So we can't easily just e.g. write a wrapper DIV as mentioned above.
I happened to be involved in a gem called Hoodoo that provides monkey patching facilities that lets you write patch modules which are more like subclasses - super is available to call up to the patched implementation - and, further, patches can be enabled or disabled dynamically and easily. Hoodoo is actually a Rack application service framework, so this is something of a sledgehammer - I always intended to one day extract this into its own gem, but at the time of writing, I have not got around to it (and several years have gone by) - but we can require just the part we need and ignore the rest.
Here, I patch SimpleForm's builder methods. These just call Rails' form helpers under the hood, so I might have a go at patching lower down in Rails instead, but anyway, the following worked.
In your Gemfile, declare the Hoodoo dependency but don't load all of its component parts as you won't want most of them.
# Hoodoo's monkey patch module is useful sometimes:
# https://rubygems.org/gems/hoodoo
#
# MUST use 'require: false' so that the Rack components of Hoodoo middleware
# do not get activated; this is a Rails app, not a Hoodoo service!
#
gem 'hoodoo', '~> 2.12', require: false
...then write something like config/initializers/simple_form_monkey_patch.rb which looks something like this:
require 'hoodoo/monkey'
module SimpleFormMonkey
module InstanceExtensions
def simple_form_for(record, options = {}, &block)
modified_options = {html: {data: {turbo: false}}}
modified_options.deep_merge!(options)
super(record, modified_options, &block)
end
end
end
Hoodoo::Monkey.register(
extension_module: SimpleFormMonkey,
target_unit: SimpleForm::ActionViewExtensions::FormHelper
)
Hoodoo::Monkey.enable(
extension_module: SimpleFormMonkey
)
...that'll do it. This has some risk as we're patching things which are - in terms of the module name & nesting - technically private to SimpleForm, but the method signature itself is at least public. You could patch ActionView::Helpers::FormHelper with an override for form_for instead, if you wanted to go lower level and patch an API that's been stable for a very long time. The code would be almost identical as the method signatures are the same.
I used Javascript to solve this problem:
document.querySelectorAll('form').forEach(function (el) {
el.dataset.turbo = false
})
No more flaky system tests due to randomly missing flash messages/alerts after form submissions and Devise also works perfectly again.
#kamilpogo your solution worked like a charm! ty!!! currently learning and following this GoRails tutorial before i ran into some turbo trouble trying to render "Thanks!" for anyone else out there.
basically, i added the javascript to in /layouts/application.html.erb like below:
<script>
document.querySelectorAll('form').forEach(function (el) {
el.dataset.turbo = false
})
</script>
<script src="js-bootstrap"></script>
</body>
</html>
UPDATE: comments in the videos have a different work around by setting turbo to 'false' and local to 'true' inside the form:
form_with model: #user, url: sign_up_path, local: true, data: { turbo:false } do |form|
I'm setting up a rails application with rails_admin and acts_as_taggable_on gems.
Earlier in the project when attempting to make sure that this could be done I found this issue on the rails_admin github page which led to this gem which is still in the list of plugins on the rails_admin github wiki. So it seems like it can be done.
I started by following the setup instructions in the READMEs for rails_admin, acts_as_taggable_on and rails_admin_tag_list. I have some models on the app and before adding any tagging functionality to them they show up and work just fine on rails_admin.
Here is an example of a model that I'm attempting to add tags to:
class Location < ActiveRecord::Base
acts_as_taggable
acts_as_taggable_on :regions
private
def location_params
params.require(:location).permit(:lat, :long, :tag_list => [], :region_list => [])
end
end
In this format I get a flash notice: "Model 'Location' could not be found" when accessing the rails admin page. The Location Model also does not show up in the list of Models.
I have not yet built out pages to add data but I did add a location to my database via the rails console and added tags to the lists for that location using the example from the acts_as_taggable_on README:
a = Location.new
a.region_list.add("awesome")
After doing this and looking at the rails_admin page again I still see the "Model 'Location' could not be found" flash notice. But I also see Location in the list of models.
Clicking on Location gives me the following error:
NoMethodError at /location
undefined method `[]' for #<RailsAdmin::Adapters::ActiveRecord::Property:0x00000101fabd90>
Better errors shows the
if tag_types.include?(properties[:name])
line below to be the line at fault:
RailsAdmin::Config::Fields.register_factory do |parent, properties, fields|
model = parent.abstract_model.model
if defined?(::ActsAsTaggableOn) && model.taggable?
tag_types = model.tag_types
if tag_types.include?(properties[:name])
name = "#{properties[:name].to_s.singularize}_list".to_sym
fields << RailsAdmin::Config::Fields::Types::TagList.new(parent, name, properties)
end
end
I'm still really quite new but it seems like there isn't a whole lot written about the interaction between these two gems at the moment. I'm grateful for any insight you can provide to get rails admin to be able to display models with tag_lists appropriately. Thanks!
Okay, let me preface this by saying I have no idea what I'm doing. But I might have a clue.
rails_admin_tag_list hasn't been updated for Rails 4, which it looks like you're using (hello, strong parameters!). And I'm guessing you're using a pretty recent version of rails_admin, since you're on Rails 4.
Based on the debugging work you've already done, it looks like the issue is with the RailsAdmin::Adapters::ActiveRecord::Property (or it's at least adjacent to your issue), which looks like it was added in newer versions of rails_admin. (Or at least that's what it looks like without thorough research.)
There's an unmerged pull request on rails_admin_tag_list that looks like it addresses that issue here.
So, what I'd suggest trying is specifying that fork/commit of rails_admin_tag_list in your Gemfile, like such:
gem 'rails_admin_tag_list', :git => 'git://github.com/imouaddine/rails_admin_tag_list.git', :ref => 'a9a4e31af6fdd2124110d0dff81ab97950803e65'
Good luck!
I want to implement friendly_id into existing model. Application uses russian gem, which handles new or hand-saved records well, but it doesn't seem to work when I update records from the command line.
User.find_each(&:save) (as friendly_id docs syggested) generate slugs like --<id>.
I used custom normalize method to provide transliterated slug:
def normalize_friendly_id(input)
Russian.transliterate input.to_s.mb_chars.downcase
end
but it definitely may miss some edge cases, and handles string differently from "normal" workflow. What I'm looking for is the way to reuse regular create/update flow and native behavior.
The best way to resolve this problem:
1) Add gem 'babosa' n your Gemfile
gem 'friendly_id'
gem 'babosa'
2) Owerride friendly_id's method in your model
def normalize_friendly_id(text)
text.to_slug.transliterate(:russian).normalize.to_s
end
I want to get next thing...
# For ArticlesController > ApplicationController
# in view
render 'articles/edit/form'
# tries 'app/views/articles/edit/_form.html.erb'
# then tries 'app/views/articles/_form.html.erb'
# then what it wants
Or maybe render with array partial option:
# For ArticlesController > ApplicationController
# in view
render_exists ['articles/edit/form', 'articles/new/form']
# tries 'app/views/articles/edit/_form.html.erb'
# then tries 'app/views/articles/new/_form.html.erb'
# then what it wants
This isn't realized, is this? But maybe some gems for 3.2 or monkeypatches... And don't you know pull requests to rails about it? Thanks!
UPD That's isn't controller-based view inheritance. This should work for (at the same page):
render `articles/edit/form`
render `comments/edit/form`
I'm using the mechanism I described in an article in the rails forum
It works a treat for me though I hear there is now some built in support in the latest versions or at least effort is under way to do add such a feature.
That already exists, and it's very similar to the controller inheritance.
You must follow a conventional strategy, however. You would put your global partial in app/views/application, then you can put a more specific one at each inherited level, like app/views/articles.
Take a look at the following railscast for more details: #269 Template Inheritance
I'm using the Rails gem SimpleForm, but I think my question may be applicable to any gem.
https://github.com/plataformatec/simple_form
It has a lot of great features and customization, but I'm looking to go a bit further. For example, I really wish the markup generated had no default classes inserted into it, but I'd still like the ability to insert my own manually. I found that I could remove some of the classes by commenting out lines in the gem files. However this is outside of my project-- I would want a DRY solution that will stay with my project when I deploy to production, preferably without having to pack all of my gems.
I imagine this is a common situation that could apply to any gem, and I should be able to override any gem wholly or partially probably by adding customs files in my project that override the gem... but I'm not sure how.
Any help would be appreciated! Thanks.
Are you talking about monkey patching? Say your gem has a class in a file
# simple_form_gem/lib/some_file.rb
class A
def some_method
puts 'A'
end
end
If you want to change the output of #some_method then you can create an initializer file and do
# config/initializers/my_monkey_patch_for_simple_form_gem.rb
class A
def some_method
puts 'duck punching'
end
end
Your monkey patch will only affect A#some_method, and not other methods in A. Just make sure the output of your monkey patch won't break something else in the gem.