Ask phone number validation only once by session - ruby-on-rails

I integrated phone number verification in my app with this tutorial
here, the problem is when the visitor go on a profil from my results page and back to the results page the modal of the phone number verification reappears
I would know how to ask a phone number only once
My phone verification view
<div class="modal show" id="myModalpin" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title"> Vérification téléphone</h4>
</div>
<div class="modal-body">
<div id="send-pin">
<h4>Nous allons vous envoyer un code par sms afin de vérifier votre numéro <br> Est-ce le bon numéro ?</h4>
<%= form_for PhoneNumber.new, remote: true do |f| %>
<div class="form-group">
<%= f.text_field :phone_number %>
</div>
<%= f.submit "Envoyer", class: "btn btn-danger", id: 'send-pin-link' %>
<% end %>
</div>
<div id="verify-pin">
<h3>Entrer votre code de comfirmation</h3>
<%= form_tag phone_numbers_verify_path, remote: true do |f| %>
<%= hidden_field_tag 'hidden_phone_number', '' %>
<div class="form-group">
<%= text_field_tag :pin %>
</div>
<%= submit_tag "Verifier", class: "btn btn-primary" %>
<% end %>
</div>
<div id="status-box" class="alert alert-success">
<p id="status-message">Status: Haven’t done anything yet</p>
</div>
</div>
</div>
</div>
</div>
<% content_for(:after_js) do %>
<%= javascript_tag do %>
$(window).on('load',function(){
$('#myModalpin').modal('show');
});
<% end %>
<% end %>

A quick and a bit dirty solution would be to add condition to the execution of your javascript.
Let say that your phone object is in #phone variable created in your controller.
then you can transform your code with
<% content_for(:after_js) do %>
<%= javascript_tag do %>
$(window).on('load',function(){
<% if #phone.nil? %>
$('#myModalpin').modal('show');
<% end %>
});
<% end %>
<% end %>
A bit cleaner would be to put it in a dedicated view file with the extension .js.erb

Related

RoR passing meeting information into a modal

I have a calendar that has meetings fed onto it.
Controller:
def index
#meetings = current_user.meetings.all
end
View
<%= render "calendar", meetings: #meetings %>
Rendering:
<%= month_calendar events: meetings do |date, meetings| %>
<%= date %>
<% meetings.each do |meeting| %>
<div>
<% unless meeting.complete == true%>
<% if meeting.end_time.to_date < Date.today %>
<%= link_to "❗️ #{meeting.name}", meeting, class: "link" %>
<% elsif meeting.end_time.to_date == Date.today %>
<%= link_to "🔔 #{meeting.name}", meeting, class: "link" %>
<% else meeting.end_time.to_date > Date.today %>
<%= link_to meeting.name, meeting, class: "link" %>
<% end %>
<% end %>
</div>
<% end %>
<% end %>
I have managed to get the link to fire a modal, but cannot figure out how to pass in the singular meeting information.
The below code shows links as individual meetings, but the modal only comes up with the first meeting information on all links:
<% if meeting.end_time.to_date < Date.today %>
<%= link_to "❗️ #{meeting.name}", meeting, {:remote => true, 'data-bs-toggle' => "modal", 'data-bs-target' => '#task_modal'} %>
<div class="modal fade" id="task_modal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-scrollable modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="staticBackdropLabel">Task name: <%= meeting.name %><br>Urgency Level: <%= meeting.priority %></h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<%= meeting.body %>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<% end %>

Nil:nil class error on each loop when Form to build object loaded on page first

I have a form on a page that is building a “tip” for a “guide”. Below the form, I am running an each loop over all the #guide.tips. I keep getting an error as the each loop is loading the forms blank object as it sees it as a tip. I’ve currently solved the problem by using jQuery to inject the form after page load, but there has to be a better solution.
Each Loop on Guide.html.erb
<% if !#guide.tips.blank? %>
<% #guide.tips.each do |tip| %>
<div class="row mx-1">
<div class="col-md-3 border-right">
<div class="float-left">
<%= image_tag avatar_url(tip.user), class: "float-left text-left align-middle rounded img-fluid mx-3", width: "30%" %>
<p><%= tip.user.fullname %></p>
</div>
<div class="float-right mr-3">
<%= link_to like_tip_path(tip), method: :put do %>
<div class="fas fa-angle-up"></div>
<%= tip.get_upvotes.size %>
<% end %><br/>
<%= link_to dislike_tip_path(tip), method: :put do %>
<div class="fas fa-angle-down"></div>
<%= tip.get_downvotes.size %>
<% end %>
</div>
</div>
<div class="col-md-8 ml-3">
<h6><%= tip.title %> -<span class="ml-1"><small><%= tip.created_at.strftime("%A, %d %b %Y %l:%M %p")%></small></span></h6>
<%= tip.tip %>
</div>
</div><hr/>
<% end %>
<% end %>
Tips_Controller.rb
def new
#guide = Guide.find(params[:guide_id])
#tip = Tip.new
end
def edit
end
def create
#guide = Guide.find(params[:guide_id])
params[:tip][:user_id] = current_user.id
#tip = #guide.tips.create!(tip_params)
redirect_to guide_path(#guide)
end
Tip Form Partial
<%= form_for([#guide, #guide.tips.build]) do |f| %>
<div class="form-group row">
<div class="col-sm-12">
<p class="text-left">Tip Title</p>
<%= f.text_field :title, placeholder: "Enter Title", class: "form-control" %>
</div>
<div class="col-sm-12 mt-2">
<p class="text-left">Your Tip</p>
<%= f.text_area :tip, placeholder:"What's your tip for this travel guide?", class: 'form-control' %>
</div>
</div>
<div class="form-group row">
<div class="col-md">
<%= f.submit 'Submit', class: 'btn btn-primary btn-block' %>
</div>
</div>
<% end %>
Here is another solution that does not separate the logic between the controller and the view and cleans up your empty array statement for your loop
Each Loop on Guide.html.erb
<% #guide.tips.each do |tip| %>
<div class="row mx-1">
<div class="col-md-3 border-right">
<div class="float-left">
<%= image_tag avatar_url(tip.user), class: "float-left text-left align-middle rounded img-fluid mx-3", width: "30%" %>
<p><%= tip.user.fullname %></p>
</div>
<div class="float-right mr-3">
<%= link_to like_tip_path(tip), method: :put do %>
<div class="fas fa-angle-up"></div>
<%= tip.get_upvotes.size %>
<% end %><br/>
<%= link_to dislike_tip_path(tip), method: :put do %>
<div class="fas fa-angle-down"></div>
<%= tip.get_downvotes.size %>
<% end %>
</div>
</div>
<div class="col-md-8 ml-3">
<h6><%= tip.title %> -<span class="ml-1"><small><%= tip.created_at.strftime("%A, %d %b %Y %l:%M %p")%></small></span></h6>
<%= tip.tip %>
</div>
</div><hr/>
<% end unless #guide.tips.blank? %>
Tip Form Partial
By creating the Tip from outside the association (i.e. not using build), it will not be loaded into the class variable's children
<%= form_for([#guide, Tip.new(guide: #guide)]) do |f| %>
<div class="form-group row">
<div class="col-sm-12">
<p class="text-left">Tip Title</p>
<%= f.text_field :title, placeholder: "Enter Title", class: "form-control" %>
</div>
<div class="col-sm-12 mt-2">
<p class="text-left">Your Tip</p>
<%= f.text_area :tip, placeholder:"What's your tip for this travel guide?", class: 'form-control' %>
</div>
</div>
<div class="form-group row">
<div class="col-md">
<%= f.submit 'Submit', class: 'btn btn-primary btn-block' %>
</div>
</div>
<% end %>
Another Example / Q&A
Using the structure you already have you could do:
<% if #guide.tips.count > 1 %> (assuming this will always be shown with an empty "build" tip)
or you can use:
<% next unless tip.persisted? %>
inside the loop, before the actual form.
You also don't need the blank? check as an .each on an empty enumerator simply won't execute the block, and as long as there's a has_many relationship between guide and tips it will always yield a collection proxy.
I would write it as:
<% #guide.tips.each do |tip| %>
<% next unless tip.persisted? %>
<div class="row mx-1">
<div class="col-md-3 border-right">
...
<% end %>

bootstrap modal for edit user profile

I have added bootstrap modal to edit user profile. It edits user profile but when there is an error in the form content it redirects to localhost:3000/user .how can I get errors in the modal itself? I used devise gem for user. what did I do wrong
_edit.html.erb
<div class="modal" id="EditProfileModal" data-keyboard="false" data-backdrop="static" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span></button>
<h4 class="modal-title">Edit user</h4>
</div>
<div class="modal-body">
<div class="container">
<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: {method: :put}) do |f| %>
<%= devise_error_messages! %>
<div class="form-group">
<%= f.label :email %><br/>
<%= f.email_field :email, autofocus: true, :value => current_user.email %>
</div>
<% if devise_mapping.confirmable? && resource.pending_reconfirmation? %>
<div>Currently waiting confirmation for: <%= resource.unconfirmed_email %></div>
<% end %>
<div class="form-group">
<%= f.label :password %> <i>(leave blank if you don't want to change it)</i><br/>
<%= f.password_field :password, autocomplete: "off" %>
<% if #minimum_password_length %>
<br/>
<em><%= #minimum_password_length %> characters minimum</em>
<% end %>
</div>
<div class="form-group">
<%= f.label :password_confirmation %><br/>
<%= f.password_field :password_confirmation, autocomplete: "off" %>
</div>
<div class="form-group">
<%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i><br/>
<%= f.password_field :current_password, autocomplete: "off" %>
</div>
<div class="actions">
<%= f.submit "Update" %>
</div>
<% end %>
<h3>Cancel my account</h3>
<p>Unhappy? <%= button_to "Cancel my account", registration_path(resource_name), data: {confirm: "Are you sure?"}, method: :delete %></p>
</div>
</div>
<div class="modal-footer">
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
header
<% if user_signed_in? %>
<header>
<%= link_to "sign out", destroy_user_session_path, method: :delete %>
<%= link_to "Edit profile", '#EditProfileModal', {'data-toggle' => "modal"} %>
<div style="text-align: center">Signed in as <b><%= current_user.email %></b></div>
</header>
<%= render "devise/registrations/edit"%>
<% end %>
Form submission always forces a page reload. You can bypass this by submitting your form as ajax request. In Rails you can do this by passing option remote: true to your form_for call. Keep in mind, that to properly handle response from server you gonna need to handle javascript event:
$('[selector]').on('ajax:success', function(e, data, status, xhr) {
// do something
})
You need to use ajax for form submission with data-remote=true.
than you need to override the update action of registrations controller,
In the update action, you can check whether there is error or not with
if resource.update_attributes(your_params)
redirect_to :back # else any where you want to redirect
else
respond_to :js
end
and in registrations/update.js.erb you can add the div for show errors.
$(".modal-body").prepend("<div><%= resource.errors %></div>")

carrierwave AJAX upload with remotipart

In my rails4 I would like to submit a form via AJAX that has a file uploaded via carrierwave. As far as I know it can be done via remotipart, but can't figure it out how I can do that. (Remotipart installed properly since it's working with refile gem that I also use in the app.)
With the current code below the form gets submitted according to the logs and it says the create.js.erb is rendered, but the code in the create.js.erb file never runs.
Rendered posts/create.js.erb (387.0ms)
What should I do?
form
<%= form_for #post, remote: true, method: :post, :html => { :multipart => true, class: "post-create-form" } do |f| %>
<img id="img_prev" style="margin-bottom:10px;" width=300 height=200 src="#" class="img-thumbnail hidden"/>
<%= f.text_area :body, placeholder: "Share something useful..", class: "form-control post-create-body" %>
<%= f.button "SHARE", class: "btn btn-primary btn-sm btn-create-post", data: {disable_with: "<i class='fa fa-spinner fa-spin'></i> Saving..."} %>
<span class="btn btn-success btn-sm btn-message-file">Upload Image
<%= f.file_field :post_image, class: "choose-message-file", id: "avatar-upload" %>
</span>
<%= f.hidden_field :post_image_cache %>
<% end %>
create.js.erb
$('ul.errors').hide();
$('.alert-danger').hide();
$('.post-index').prepend('<%= j render #post %>');
$('.post-create-body').val('');
$('.btn-create-post').prop('disabled',true);
_post.html.erb
<div class="col-md-2">
<%= link_to user_path(post.user) do %>
<%= image_tag post.user.avatar.url(:base_thumb), class: 'post-avatar' %>
<% end %>
</div>
<div class="col-md-8">
<div class="post-info">
<%= link_to user_path(post.user) do %>
<span class="post-user-name"><%= post.user.full_name %></span>
<% end %>
<span class="post-updated"><%= local_time_ago(post.updated_at) %></span>
</div>
<div class="post-body">
<%= simple_format(find_links(h post.body)) %>
</div>
<div class="post-image" data-postlink="<%= post_path(post) %>">
<% if post.post_image? %>
<button data-toggle="modal" data-target="#post-image-modal">
<%= image_tag post.post_image.url(:base_thumb) %>
</button>
<% end %>
</div>
</div>
UPDATE:
The problem is connected to updating the post object. The update form code can be found in the _post.html.erb, so that's why <%= j render #post %> didn't work. Still don't know what the problem is.
So what works:
1. creating post that has no image
2. updating post that has no image
3. updating post that has image BUT image is not edited
Not working:
1. creating post that has image
2. updating post that has image which is edited
<%= form_for post, method: :patch, remote: true, :html => { :multipart => true } do |f| %>
<div class="modal fade updatepost" id="updatepost_<%= post.id %>" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content" style="text-align:left">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="edittaskmodalohhhhh">Edit Task</h4>
</div>
<div class="modal-body">
<div class="alert alert-danger" style="display:none">
<ul class="errors" style="display:none">
<%= render 'layouts/error_messages', object: f.object %>
</ul>
</div>
<div class="field form-group">
<%= f.file_field :post_image, id: "avatar-upload-update" %>
<%= f.hidden_field :post_image_cache %>
</div>
<div class="field form-group">
<%= f.text_area :body, class: "form-control edit-post-body" %>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal" id="updatepostclose">Close</button>
<%= f.button "Update post", class: 'btn btn-primary edit-post-submit', data: {disable_with: "<i class='fa fa-spinner fa-spin'></i> Saving..."} %>
</div>
</div>
</div>
</div>
<% end %>
update.js.erb
$("ul.errors").html("");
<% if #post.errors.any? %>
$('.alert-danger').show();
$('ul.errors').show();
<% #post.errors.full_messages.each do |message| %>
$("ul.errors").append($("<li />").html("<%= message.html_safe %>"));
<% end %>
<% else %>
$('ul.errors').hide();
$('.alert-danger').hide();
$('#updatepost_<%= #post.id %>').modal('hide');
$post = $('<%= j render #post %>');
editPostHideDanger($post);
$('#post_<%= #post.id %>').remove();
$(".new-post-insert").prepend($post);
$("html, body").animate({ scrollTop: 0 }, "slow");
<% end %>
There was some issue (still don't know what) with the bootstrap modals. I changed the structure of the modals and now it's working fine.

Submitting a form doesn't work after time, only after refreshing

I have a Simple Form and i just realized that if edit the form long enough (5-10secs) the Submit button suddenly doesn't work.
If i refresh the page and quickly type some letters and the submit it, it works...
This behavior is active on everything in my app that has a scaffold form, for example my Devise form's are just fine.
I have no idea what is causing this behavior.. What am i missing ?
EDIT
This behavior occurs only in Google Chrome Browsers.
<div class="panel panel-default">
<div class="panel-heading">
<div class="panel-title">
<h1>Test Form</h1>
</div>
</div>
<div class="panel-body">
<%= form_for(#question) do |f| %>
<% if #question.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#question.errors.count, "error") %> prohibited this question from being saved:</h2>
<ul>
<% #question.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="form-group">
<%= f.label :title %><br>
<%= f.text_field :title, class: "form-control", :autofocus => true,
placeholder: "#"%>
</div>
<div class="form-group">
<%= f.label :body %><br>
<%= f.text_area :body, class: "redactor redactor-box" %>
</div>
</div>
<div class="panel-footer">
<div class="form-group">
<%= f.submit "Post", class: "btn btn-primary" %>
</div>
</div>
<% end %>
</div>
It seems that the problem was in the HTML.
I wrapped all my html tags with form_for and for now it seems to be working..

Resources