ruby on rails add div on error messages join - ruby-on-rails

current code for the ajax call:
#return = { :error => true, :response => #invitation.errors.full_messages.join("<br />") }
the errors now appear as
Email can't be blank
Email is invalid
how can i add a div before the error messages and a p tag in each line?
so it would become
<div>
<p>Email can't be blank</p>
<p>Email is invalid</p>
</div>

Something like this could work for you:
error_message = content_tag :div, #invitation.errors.full_messages.map {|error| "<p>#{error}</p>"}.join
#return = { :error => true, :response => error_message }

Related

Filter select fields based on previous select fields values

I'm new at RoR and I'm having a trouble in my app. The problem consists on filter a select field named "Solution", based on the others select fields above it.
Now, what the app do is to retrieve all information from BD about Area, Region, Associated, Solution and populate the select fields with these data. But the user wants that, when an area, a region and an associated is selected by the user, only the solutions about that associated in that region on that area should be shown.
Edit:
I'm almost there! I've made many changes in my app. The select fields are populated by controller action new and the function "populate_selects", which is called by the parameter before_action :popula_selects, only: [:new, :edit]. A new function was created in order to be called by AJAX and upgrade the "Solution" field:
Atendments_Controller < ApplicationController
before_action :populate_selects, only: [:new, :edit]
def new
#atend = atendment.new
end
def update_solution #AJAX
#solutions = atendment.joins(:solution).where("atendment_area_id = ? and atendment_region_id = ? and atendment_assoc_id = ?", params[:atendment_area_id], params[:atendment_region_id], params[:atendment_assoc_id])
respond_to do |format|
format.js
end
end
private
def populate_selects
#atendment_area = atendmentArea.where(status: true, user_id: current_user.id)
#atendment_region = atendmentRegion.where(status: true, user_id: current_user.id)
#atendment_assoc = atendmentRegionAssoc.where(status: true, assoc_id: current_user.entidade_id).where(atendment_region_id: #atendment_region.map(&:atendment_region_id))
#solutions = atendment.joins(:solution).where("atendment_area_id = ? and atendment_region_id = ? and atendment_assoc_id = ?", params[:atendment_area_id], params[:atendment_region_id], params[:atendment_region_assoc_id])
end
end
Below, the _form.html.erb code from view:
<div class="atendment-form">
<%= form_for :atendment, url: {action: "new"}, html: {method: "get"} do |f| %>
<div class="col-xs-6">
<%= f.select :atendment_area_id, options_for_select(#atendment_area.collect { |c| [ c.atendment_area.name, c.id ] }, 1), {:prompt=>"Área"}, { :class => 'form-control', :required => true, id: 'atendment_atendment_area_id' } %>
</div>
<div class="col-xs-6">
<%= f.select :atendment_region_id, options_for_select(#atendment_region.collect { |c| [ c.atendment_region.name, c.id ] }, 1), {:prompt=>"Região"}, { :class => 'form-control', :required => true, id: 'atendment_atendment_region_id' } %>
</div>
</div>
</div>
<div class="field">
<%= f.select :atendment_assoc_id, options_for_select(#atendment_assoc.collect { |c| [ c.atendment_region.name, c.id ] }, 1), {:prompt=>"Associado"}, { :class => 'form-control', :required => true, id: 'atendment_atendment_assoc_id' } %>
</div>
<div class="field">
<%= f.select :solution_id, options_for_select(#solutions.collect { |solution| [solution.name, solution.id] }, 0), {:prompt=>"Solução"}, { :class => 'form-control', :required => true, id: 'atendment_solution_id' } %>
</div>
</div>
Route to the new function:
resources :atendments do
collection do
get :update_solution
end
end
AJAX function which calls the "update_solution" and reset solution field's value (app/assets/javascript/atendment.js.coffee):
show_solutions = ->
$.ajax 'update_solution',
type: 'GET'
dataType: 'script'
data: {
atendment_area_id: $("#atendment_atendment_area_id").val()
atendment_region_id: $("#atendment_atendment_region_id").val()
atendment_assoc_id: $("#atendment_atendment_assoc_id").val()
}
error: (jqXHR, textStatus, errorThrown) ->
console.log("AJAX Error: #{textStatus}")
success: (data, textStatus, jqXHR) ->
console.log("OK!")
$(document).ready ->
$('#atendment_atendment_assoc_id').on 'change', ->
show_solutions()
So, I've created a .coffee file to render the partial that will return a new value to the "solution" field "option" tag
(app/views/atendment/update_solution.coffee):
$("#atendment_solution_id").empty()
.append("<%= escape_javascript(render :partial => 'solution') %>")
And, the last but not least, the partial containing the html code for the "option" tag mentioned above (app/views/atendments/_solution.html.erb):
<option value="<%= solution.id %>" selected="selected"><%= solution.nome %></option>
For any reason, the AJAX function doesn't print nothing on console (nor error neither success), but it calls the update_solution.coffee file. The point is, it doesn't update the option value due an error (500 internal server error). I don't know what am I doing wrong. If anybody could help me, I appreciate it.
I would do this with JS, can think any other way.
A function called by onchange that change the display attribute from each field that you need to hide or show.
I solved this with the following code:
assets/js/atendments.js
I changed the code because the last one had many bugs.
function getAssociated(){
var aau_id = $("#atendment_area_user_id").val()
var aru_id = $("#atendment_region_user_id").val();
$.getJSON("/controllers/atendments_controller/getAssociated/"+aru_id,
function ( callback ) {
if (callback != "error"){
var assoc = document.getElementById("atendment_region_associated_id");
while (assoc.firstChild) {
assoc.removeChild(assoc.firstChild);
}
var i = Object.keys(callback).length -1;
$("#atendment_region_associated_id").append("<option value=''>Associated</option>");
while (i >= 0) {
$("#atendment_region_associated_id").append("<option value='"+callback[Object.keys(callback)[i]]+"'>"+Object.keys(callback)[i]+"</option>");
i--;
}
}
});
get_solution_type();
}
function get_solution_type() {
var ara_id = $("#atendment_region_associated_id").val();
$.getJSON("/controllers/atendments_controller/getSolution/"+ara_id,
function ( callback ) {
if (callback != "error"){
var sol = document.getElementById("atendment_solution_id");
while (sol.firstChild) {
sol.removeChild(sol.firstChild);
}
var i = Object.keys(callback).length-1;
while (i >= 0) {
$("#atendment_solution_id").append("<option value='"+callback[Object.keys(callback)[i]]+"'>"+Object.keys(callback)[i]+"</option>");
i--;
}
}
});
var aau_id = $("#atendment_area_user_id").val();
$.getJSON("/controllers/atendments_controller/getType/"+aau_id,
function ( callback ) {
if (callback != "erro"){
var type = document.getElementById("atendment_type_id");
while (type.firstChild) {
type.removeChild(type.firstChild);
}
var i = 0;
while (i < (Object.keys(callback).length)) {
$("#atendment_type_id").append("<option value='"+callback[Object.keys(callback)[i]]+"'>"+Object.keys(callback)[i]+"</option>");
i++;
}
}
});
}
The $.getJSON performs ajax request to the controller that responds with JSON and update the select fields option tags.
controllers/atendments_controller
I just retrieve the data from DB and return as JSON
def getAssociated
aru_id = params[:atendment_region_user_id]
aras = AtendmentRegionAssociated.where("SQL here")
if aras.present?
render :json => aras.to_json
else
render :json => "error".to_json
end
end
def getSolution
ara_id = params[:atendment_region_associated_id]
sol = Solution.where("SQL here")
if sol.present?
render :json => sol.to_json
else
render :json => "error".to_json
end
end
def getType
aau_id = params[:atendment_area_user_id]
type = AtendmentType.where("SQL here")
if type.present?
render :json => type.to_json
else
render :json => "error".to_json
end
end
Update the routes and put the javascript functions in select fields onchange property. Now everything is working fine :D

How to send email based on date time in Rails?

I am having a "send email" functionality in my application which sends email to the email addresses.
Later a new functionality is added where when the user checks on "Send email later" radio button, selects date and time and clicks on send email button so that the email is sent at particular time.
For this I added a field into database with column "send_reports_at", added to controller and required actions.
The date time is stored as : "2016-11-01 16:15".
How to add the condition of sending email based on the date time in my application(I am new to delayed job and all)?
Please help.
This is my view:
<%= f.input :additional_emails, :label => false, :input_html => {:id => 'sponge_contacts', :placeholder => 'Separate emails by comma', :class => 'deliver_page_email', :type => 'text', :rows => 2, :style=> 'width:300px; border-color:#ccc; font-size:13px; padding:10px 0 0 10px; width: 295px; height: 110px; resize: none;'} %>
<input type="radio" id="send_email_0" name="send_email" value="now" checked> Send email now<br>
<input type="radio" id="send_email_1" name="send_email" value="later"> Send email later<br>
<%= f.input :send_reports_at,:label => false, :input_html => {:placeholder => 'Click here to select date and times', :class => 'deliver_page_email', :type => 'text', :rows => 2} %>
<% content_for :javascript do %>
<script type="text/javascript">
$( function() {
$( "#report_send_reports_at" ).datepicker();
} );
$(document).ready(function() {
$("#report_send_reports_at").hide();
$("#send_email_0, #send_email_1").bind('change click',function(){
toggleResult();
});
});
function toggleResult(){
result = $("[name='send_email']:checked").val();
if(result == "later"){
$("#report_send_reports_at").show();
}else{
$("#report_send_reports_at").hide();
}
}
</script>
<% end %>
<% end %>
<%= link_to "Send Now", '#', :class => "pink_button _round_5", :id => 'send_now_button' %>
This is my controller method:
def send_report_email
send_to_agents = params.has_key?("send_to_agents") && params["send_to_agents"] == "true"
if #report.photos.empty?
Screenshot.delay.new(#user.id, #report.id, Rails.application.config.custom.indicator_screenshot_bucket)
else
Screenshot.delay.new(#user.id, #report.id, "photo_screenshots")
end
Screenshot.delay.new(#user.id, #report.id, Rails.application.config.custom.report_screenshot_bucket)
if #report.update_attributes(params[:report])
set_photo_position(false)
#report.save
if send_to_agents
#report.update_attribute(:duplicable, true)
#good_emails, #bad_emails, #unsubscribed_emails = #user.account.users.map(&:email), [], []
else
#good_emails, #bad_emails, #unsubscribed_emails = filter_emails(#report.additional_emails)
#user.delay.add_new_contacts(#good_emails)
end
#good_emails.each do |email|
send_to_agents == true ? ReportMailer.delay.additional_emails(email, #user, #report, "A new report is available: #{#report.title}") : ReportMailer.delay.additional_emails(email, #user, #report)
end
ReportMailer.delay.report_sent(#user, #report, #good_emails, #bad_emails, #unsubscribed_emails)
end
respond_to do |format|
format.json { render :json => { :success => true, :report_id => #report.id, :redirect => user_reports_url(current_user), :notice => 'Report was successfully sent!' } }
end
end
You could write a function (for instance a class method for ReportMailer) that sends all of the email whose scheduled time matches or is less than the current time, then set a cron job to use rails runner to run that function as often as necessary.

Select option required Ruby Rails

I have a mix of ruby rails code
I have a form with a selection option that i want to be a required, and i want to validate. If user do not select anything i want to validade with a error message.
However, I try to copy past code from internet, I'm new at ruby rails and I still not have a error message.
I also check that i use 'required' , or if i use 'validates_presence_of' doesn't make difference because it's a submit form (i think)
test_filteR_form.rb
class TestFilterForm < ApplicationForm
attribute :model, String
validates_presence_of :model
end
.html.erb
<%= f.input :fill_form_error_message,:as => :hidden, :input_html => { :value =>I18n.t('test.fill_form_error') } %>
<%= f.input :model, label: I18n.t('test.filters.model'), autofocus: true, input_html: {class: 'input-xlarge chosen-select' }, collection: TestType.options_for_select, include_blank: true %>
"/>
controller
def paginate
#test_form = TestForm.new(params)
unless #test_form.valid?
#model = params[:test_filter_form][:model]
#h_model = #model.pluralize + 'H'
#history, _query, #test_fields = TestQueryService.search!(params)
session[:test_query] = _query
session[:test_klass] = #model
else
format.json { render :json => { :error => #test_form.errors.full_messages }, :status => 422 }
end
js.coffee
$contentDiv.on 'ajax:error', 'form[data-value]', (event, xhr, status, error) ->
data = $.parseJSON(xhr.responseText)
$result = $(#).parents('tr').find('[data-result]')
controller.resultUpdateError xhr.status, $result.data('result'), data, $(#)
# Hide row loading spinner
$(#).parents('tr').find('span[role="result_update_spinner"]').hide()
# Hide saved form
$(#).parents('tr').find('.saved_form').hide()
resultUpdated: (result, data, $form) ->
if data.flash != undefined
# Sets a sucess message on page top
flash data.flash.type, data.flash.message
# Sets a success message on row
$fieldForm = $form.parents('tr').find(".messages")
$fieldForm.find('.controls').empty()
$fieldForm.find('.control-group .controls').css('color', 'green').append #_inlineMessage("Gravado com sucesso")
# Hide success message after some time
setTimeout ((self) ->
->
$fieldForm.find('.control-group .controls').empty()
return
)(this), 4000
Since you are dynamically created the selection box then there must be a default value selected which is not nil so there is no change seen you can manually create selection like this:
<div class="form-group">
<%= f.label :select_user_country %><br/>
<select class="form-control select2" name="user[country_id]">
<option value="" selected disabled>Select a Country</option>
<%#countries.each do |country|%>
<option value="<%=country.id%>"><%=country.name%></option>
<%end%>
</select>
</div>

Field with auto_complete

newbe question here.
I've inherited a rails project and been asked to change some chunk of code, but I have a very little experience in Ruby and Rails (I am an objective-c with a PHP background developper)
So the first stuff I have to had is a textfield with an auto complete mode. Actually my code has this code for the auto completed text field :
registration_controller.rb
def auto_complete_for_training_title
puts "auto_complete_for_training_title"
current_locale = params[:locale].to_s
if current_locale == 'en' then
if current_user.member then
Locale.set current_user.member.written_language
else
Locale.set 'fr'
end
end
#trainings = Training.find(:all, :conditions => ["((title LIKE ? OR fso_id LIKE ?) and is_private = 0", '%' + params[:training][:title] + '%', '%' + params[:training][:title] + '%'])
puts #trainings.count
render :partial => 'complete_ajax_own_function_training'
end
In the view, the text field is created like this :
<% form_for :sortRegistration, { :url => { :action => 'index'} } do |f| %>
<p><label><%= "Display registrations by training".t %> :</label>
<%= text_field_with_auto_complete :training, :title, { :size => 50, :tabindex => 1 },
{ :select => 'mon_titre',
:after_update_element => "function(element,val)
{
var nodes = val.select(['.value_title']) || [];
if(nodes.length>0)
{
$('sortRegistration_training_id').value = Element.collectTextNodes(nodes[0], 'value_title');
}
}"
}
%></p>
<input id="sortRegistration_training_id" name="sortRegistration[training_id]" type="hidden" size="20" value="" />
<% end %>
If I copy / paste the code, only one textField works, I've tried to change some parameters but still not changing something.
P.S. As I said I am new in the RoR, I do not know if you need more code for help me so please, feel free to ask more, I will edit my question

Mandrill API Templating

I'm using Mandrill's Ruby API Gem and have the follow simple template for testing:
<html>
<body>
<h1 mc:edit="header">testastic</h1>
<hr/>
<br/><br/>
<div mc:edit="main_section"></div>
<hr/>
<div mc:edit="footer"></div>
</body>
</html>
Following the example on Heroku's guide I have the follow Ruby code:
require 'mandrill'
m = Mandrill::API.new
rendered = m.templates.render 'test-template', [{:header => 'some header text', :main_section => 'The main content block', :footer => '<h3>asdf</h3>'}]
mail(:to => "Jayson Lane <jayson#domain.com>", :subject => "Test Email") do |format|
format.html { rendered['html'] }
#format.text { render "test" }
end
This works great and the email sends my template just fine, however, it doesn't replace the template mc:edit variables. Am I missing something?
You need to construct a hash for each element you're trying to replace. For instance, I have this inside of a template:
<h3 mc:edit="plan_info_name"> </h3>
<span mc:edit="plan_info_description"> </span>
<span mc:edit="plan_info_benefits"> </span>
And this on the mailer:
mandrill.messages.send_template(template,[
{
:name => 'plan_info_name',
:content => extra[:membership_info].name
},
{
:name => 'plan_info_description',
:content => extra[:membership_info].long_description
},
{
:name => 'plan_info_benefits',
:content => benefits_list
}
....

Resources