Problem
This is a simple question, I've looked around spree forums, plataforma tec forums and SO with no success.
We want to use two separate simple_form configurations, one for our main application and another for a spree engine store we have mounted on a specific url.
More detailed Explanation
Currently in we're developing an application using the spree engine. This means that the spree engine is mounted on a specific url and is activated by going to mysite.com/store, for example.
Now, on the main app, we're using a different set of assets than those of the spree store. Our original simple_form.rb initializer was created specifically for these assets.
Here's where it gets interesting.
Within the spree engine, we're developing a new form using simple_form as well. It works fine, but it's using the simple_form.rb file of our main app, which uses the main app's css tags and markup.
We need to modify the simple_form.rb file to actually use the spree template's css in order for things to display correctly.
Possible solutions?
Ideally we should have a simple_form.rb file for the spree engine and one for the main app, but I haven't figured out a straight forward way of doing this...
My other idea was to have some sort of conditional in the simple_form.rb file for it to load one set of options when we're on the main app and another set of options when in the spree store... maybe checking the url?
Ok, so apparently it is pretty obvious how to have separate configurations for simple_form.
Everything goes into a single simple_form.rb initializer. the only thing that changes is the config.wrapper.
SimpleForm.setup do |config|
# Wrappers are used by the form builder to generate a
# complete input. You can remove any component from the
# wrapper, change the order or even add your own to the
# stack. The options given below are used to wrap the
# whole input.
config.wrappers :default, :class => :input do |b|
# config goes here
end
config.wrappers :special, :class => input do |b|
# special config goes here
end
config.default_wrapper = :default
end
Then in your code, if you want to use the :special wrapper just write in your input like so
f.input :name, :wrapper => :special
you can find more info here
Custom Wrappers
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'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
I have the front end of a website built. It is made from a number of HTML, JavaScript, and Jquery files. Is there a way to take those files and move them into a Ruby on Rails environment so that I don't need to remake everything?
Sure. Create a new rails app (rails new app-name). Copy your existing javascript files into the Rails project at public/javascripts/. Your views/html are a bit more dependent on how you want to grow.
One option is to create a single PagesController and not bother with resources/models/etc, and you would just put all of your "views" into /app/views/pages/. You don't even have to rename them to .html.erb like you would conventionally see — you can leave them as just plain html. Your routes.rb file would look something like this:
get '/:action', :controller => 'pages', :as => 'page'
Which would afford you routes like "example.com/hello_world" that would route to PagesController#hello_world, rendering "app/views/pages/hello_world.html". If you want to use ERb, you can add that ".erb" suffix to your view file and then you can use the page_path helper to assemble links:
<%= link_to 'Hello World Demo', page_path('hello_world') %>
You will still probably want to extract the common elements into a layout at app/views/layouts/application.html.erb (again, the ERb being optional).
Another route would be to actually separate your application into resources. If you have a page that lists books, for example, you could create a BooksController and put the relevant view under app/views/books/index.html. This doesn't make sense to do if you're not going to provide some additional functionality in the future, though.
I have two RoR3 applications (APP1 and APP2)
www.subdomain1.example.com
www.subdomain2.example.com
and I want to show on APP1 some views from APP2.
I tried to do that using a 'Net::HTTP' request (code in APP1)
Net::HTTP.get( URI.parse("http://www.subdomain2.example.com/users/new") )
but the response is not evaluated as HTTP code. Among other things I do not know if there are other techniques to do what I want in more easy way.
So, is it possible to render partials from APP1 to APP2 using the common and easy approach of rendering partials in the same RoR application?
Example:
render :partial => "/users/new"
If so, how can I do that?
Here, try this:
module ApplicationHelper
require 'open-uri'
def render_url(url)
open url do |f|
f.read.html_safe # remove the 'html_safe' if you're on Rails 2.x
end
end
end
In your view:
<%= render_url 'http://ilikestuffblog.com/' %>
It will work. Just one problem, though: if the site contains relative links to images, other pages, or anything else, those links will not be shown correctly. Try this to see a bunch of blank images:
<%= render_url 'http://www.ducklet.com/' %>
Also, BE WARNED that if you don't own the URL you're including, you will be subject to cross-site scripting weirdness.
If the two applications share a filesystem or have access to a shared filesystem, then you can reference a partial directly by file path. From the Rails guide on rendering:
2.2.4 Rendering an Arbitrary File
The render method can also use a view
that’s entirely outside of your
application (perhaps you’re sharing
views between two Rails applications):
render
"/u/apps/warehouse_app/current/app/views/products/show"
Rails determines that this is a file
render because of the leading slash
character. To be explicit, you can use
the :file option (which was required
on Rails 2.2 and earlier):
render :file =>
"/u/apps/warehouse_app/current/app/views/products/show"
The :file option takes an absolute
file-system path. Of course, you need
to have rights to the view that you’re
using to render the content.
It might be more prudent to create a gem that has any shared code (ie. partials) in it so both apps can use it.
I have followed the directions posted on ReCaptcha's site about integrating Recaptcha into my application. However when I go to view it on my localhost I just get the code for get_captcha() instead of the widget. I have made the public keys available in my environment.rb file, added the recaptcha::apphelper to my application controller, and chained my vaildation, I have also included the recaptcha::viewhelper to my application helper. Am I missing a step in adding it, or is there another resource that would make this work better?
In the view you must use an ERB output block (<%=) to make this output the captcha:
<%= raw(get_captcha(:options => {:theme => 'white', :tabindex => 10) %>
Anything not in this (or it's brother, the ERB evaluation block (<%)) will be treated as plain text.