Recaptcha gem needs a failed subimission on Rails7 - recaptcha

A working form with recaptcha moved from rails6 to rails7 always arises a recaptcha validation error at first submit. On second submit it works.
= form_with url: mail_submit_path do |form|
= render partial: "err_details", locals: {field: :email}
.field
%label.label email
.control.has-icons-left
= form.text_field :email, value: #email, required: true, class: "input"
%span.icon.is-left
%i.fas.fa-envelope{:'aria-hidden' => "true"}
= render partial: "err_details", locals: {field: :captcha}
.field
.recaptcha
= recaptcha_tags
.field
.control
= form.submit "Submit", class: "button is-link"
On first submit some data is missing: from the rails logs:
I, [2022-01-18T18:42:23.795409 #1451245] INFO -- : [3c877c6c-5a2a-46e5-8ff6-5338c36d1078] Parameters: {"authenticity_token"=>"[FILTERED]", "email"=>"someone#gmail.com", "g-recaptcha-response"=>" ", "commit"=>"Submit"}
I would think it is a turbo issue, but not sure.

I was having the same issue in Rails 6.1.4. For some reason, changing
<%= recaptcha_tags %>
to
<%= recaptcha_tags(noscript: false) %>
worked for me.
I'd also like to add that I've had more success disabling Turbo for forms using recpatcha tags.
<%= form_with(model: #resource, local: true, data: { turbo: "false"}) do |f| %>

Related

Stimulus ajax:response not returning the server response data

I am starting a new Rails 7 app and recently found out that we can't use ujs anymore :( I found a plugin called mrujs which is working correctly to send my forms remotely to the server. I am also using stimulus to handle various javascript functions on the page.
The issue that I'm having is my response back after ajax:success processes is not iterable:
TypeError: object is not iterable (cannot read property Symbol(Symbol.iterator))
Below is my HTML, Rails, and Stimulus Code:
HTML
<%= form_with model: Article.new, html: { data: { remote: true, type: "html", "action": "ajax:success->modal-forms#onPostSuccess ajax:error->modal-forms#onPostError" } } do |f| %>
<%= f.label :title, "Article Title" %>
<%= f.text_field :title, class: "form-control" %>
<%= f.submit "Save Article", class: "btn btn-primary" %>
<% end %>
Ruby / Rails
def create
#article = Article.create(article_params)
if #article.errors.any?
render partial: 'error', article: #article, status: :bad_request
else
render #article
end
end
This returns a basic html page that would be inserted into another location within the page.
<li><%= #article.title %></li>
Stimulus Action
onPostSuccess(event) {
event.preventDefault()
const [data, status, xhr] = event.detail
// This is where I get the issue of 'Not Iterable'
}
event.detail gives me the not iterable error. Does anyone know how I can get my response from rails to be formatted so the [data, status, xhr] section will actually work?
If hotwire or turbo is needed for this an example would be extremely helpful :)
Thanks
Eric
This may not be the correct way but it does work:
html
<div data-container="remote">
<%= form_with model: Person.new, html: { data: { "action": "submit->remote#submit" } } do |f| %>
<%= f.text_field :first_name %>
<%= f.submit :submit %>
<% end %>
</div>
peole rails controller
def create
#person = Person.new(person_params)
if #person.save
render json: #person
else
render partial: 'people/person', locals: { person: #person }, status: :unprocessable_entity
end
end
remote stimulus controller
submit(event) {
event.preventDefault()
fetch(event.target.action, {
method: 'POST',
body: new FormData(event.target),
}).then(response => {
console.log(response);
if(response.ok) {
return response.json()
}
return Promise.reject(response)
}).then(data => {
console.log(data)
}).catch( error => {
console.warn(error)
});
}

Rails Simple Form input with Font-Awesome

I want to use icons instead of text for labels in a horizontal simple_form. However, I am unable to separate the text from the icons
= simple_form_for #user, html: { class: 'form-horizontal' }, wrapper: :horizontal_form do |f|
# shows 'username' label only
= f.input :username
# shows icon with 'username'
= f.input :username, label_html: {class: "fas fa-user"}
# shows nothing
= f.input :username, label_html: {class: "fas fa-user"}, label: false
For those who want to do the same, there is a simpler/cleaner way :
= f.label :username, label: ('<i class="fas fa-user"></i>').html_safe
= f.text_field :username
Also work with I18n localization file :
(en.yml)
username: '<i class="fas fa-user"></i>'
then
= f.label :name, label: t(:username).html_safe
= f.text_field :username
Using simple_form (4.1.0)
Hope this help.
You can use the wrapper_html option:
= f.input :username, label: false, wrapper_html: { class: 'fa fa-user' }
You will probably have to add some css to make it look the way you want. For example, to get the icon on a different line than the input, I had to add display: block to the icon.
wrapper_html: and label_html: were complicated, so I just did it manually
.row
.col-3
.text-right
i.fas.fa-user
.col-9
= f.input_field :username, label: false, class: 'form-control'
I've just implemented this very thing on my own project. There was a really simple solution.
First, I created a helper for outputting fontawesome icons. In app/helpers/font_awesome_helper.rb:
module FontAwesomeHelper
def fa_icon(icon, style: :regular)
content_tag(:i, "", class: [icon_style_class(style), icon_class(icon)].join(" "))
end
private
def icon_class(icon)
"fa-#{icon}"
end
def icon_style_class(style)
case style
when :light, :l
"fal"
when :regular, :r
"far"
when :solid, :s
"fas"
when :duotone, :duo, :d
"fad"
else
"fa"
end
end
end
You can extend this further to support inverting icon colours, flipping horizontally, etc.
Finally, you can use your fa_icon helper in your simple-form input:
= f.input :username, label: fa_icon("user", style: :solid)

Heroku records a fixnum instead of a string

Locally it records a string as expected and on Heroku it records a fixnum...
A user can create a wish and select an area where he wants to see a concert. In order to receive an email if a concert matches his wish.
I have a hash sotred in my application_helper.rb as a constant
DEPARTMENTS = {
"01" => "Ain",
"02" => "Aisne",
"03" => "Allier"
#........
}
My create method in the wanted_concerts_controller.rb looks like this
def create
#wanted_concert = WantedConcert.new(wanted_concerts_params)
#wanted_concert.user_id = current_user.id
if #wanted_concert.save!
redirect_to wanted_concerts_path, notice: "Ton souhait est bien enregistré"
else
render :new , alert: "Oups recommence!"
end
end
private
def wanted_concerts_params
params.require(:wanted_concert).permit(:department, :user_id)
end
In the new.html.erb file I can make my wish
<%= simple_form_for(#wanted_concert) do |f| %>
<%= f.input :department, prompt: "Choisi une région", label: false, collection: ApplicationHelper::DEPARTMENTS.map { |k, v| v } %>
<%= f.submit "Valider", class: "btn btn-success" %>
<% end %>
And this is my index.html.erb where the wishes are displayed
<% #wanted_concerts.each do |wanted| %>
<li> <%= wanted.department %> <%= link_to "Supprimer", wanted_concert_path(wanted), method: :delete %></li>
<% end %>
So locally if I chose for exemple Ain
the index display Ain
and on Heroku if chose Ain
it display 0
So On Heroku console I did:
irb(main):004:0> c = WantedConcert.last
D, [2018-03-04T13:31:54.314672 #4] DEBUG -- : WantedConcert Load (1.3ms) SELECT "wanted_concerts".* FROM "wanted_concerts" ORDER BY "wanted_concerts"."id" DESC LIMIT $1 [["LIMIT", 1]]
=> #<WantedConcert id: 21, department: 0, user_id: 1, created_at: "2018-03-04 13:02:16", updated_at: "2018-03-04 13:02:16">
irb(main):005:0> c.department.class
=> Integer
irb(main):006:0>
I found help.
I did a naughty mistake, I renamed a field in an old migration instead of renaming in a new....
So this may help someone facing a smiliar error...

rails 4: Adding a class to a select tag

Trying to add a class to a select tag
<%= f.select(:ptype, options_for_select(TourParticipation::PTYPES, selected: "traveler", disabled: "Role:") , { :class => "widens" } ) %>
results in
<select name="tour_participation[ptype]" id="tour_participation_ptype"></select>
Why is the class not applied to my select tag?
You forget that before html_options is options hash. Try this:
<%= f.select(:ptype, options_for_select(TourParticipation::PTYPES, selected: "traveler", disabled: "Role:") , {}, { :class => "widens" } ) %>
See definition:
http://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.html#method-i-select

uploadify and paperclip on rails 3.1

i'm trying simply to upload a file using uploadify and paperclip.
This is index view:
<%- session_key = Rails.application.config.session_options[:key] -%>
$('#upload').uploadify({
'uploader' : 'uploadify.swf',
'script' : '/videos',
'cancelImg' : 'images/cancel.png',
'buttonText' : 'Add video!',
'folder' : '/public',
'auto' : true,
'scriptData' : {"<%= key = Rails.application.config.session_options[:key] %>" : "<%= cookies[key] %>",
"<%= request_forgery_protection_token %>" : "<%= form_authenticity_token %>",
},
onError : function (event, id, fileObj, errorObj) {
alert("error: " + errorObj.info);
}
});
This is my model:
class Video < ActiveRecord::Base
has_attached_file :source
validates_attachment_presence :source
end
...and this is my migration file:
class CreateVideos < ActiveRecord::Migration
def self.up
create_table :videos do |t|
t.string :source_content_type
t.string :source_file_name
t.integer :source_file_size
t.timestamps
end
end
def self.down
drop_table :videos
end
end
Now, when i upload a file, there aren't errors raised, neither client side, nor server side, but it looks like paperclip doesn't get the parameters sent him by uploadify. In fact, if i remove validation from model, resource is created without parameters.
In controller i add:
def create
logger.info(params.inspect) (1)
#video = Video.new(params[:video])
#video.save
logger.info #video.inspect (2)
end
In development.log (1) gives me
{"Filename"=>"prova.mov", "authenticity_token"=>"9q5w5LipGoBj Iac055OPbDofFU5FMbpEX675 RqOqs=", "folder"=>"/public", "_StreamVideo_Api_session"=>...
(2) without validation
#<Video id: 1, source_content_type: nil, source_file_name: nil, source_file_size: nil, created_at: "2011-10-10 12:12:38", updated_at: "2011-10-10 12:12:38">
(2) with validation
#<Video id: nil, source_content_type: nil, source_file_name: nil, source_file_size: nil, created_at: nil, updated_at: nil>
Where may be the problem?
Thank you in advance for answers!
In my view i put:
<h1>New video</h1>
<% form_for :video, :html => { :multipart => true } do |f| %>
<%= f.file_field :source%>
<% end %>
But http://localhost:3000/videos/new shows me only the title!!
the code looks ok, you should just add there encodeURI function. In Uploadify 2.1
it should work with:
'scriptData' : {
$('meta[name=csrf-param]').attr('content') : encodeURI(encodeURIComponent($('meta[name=csrf-token]').attr('content')))
}
With Uploadify 3.1:
'formData': {
$('meta[name=csrf-param]').attr('content') : encodeURI($('meta[name=csrf-token]').attr('content'))
}

Resources