rails 4 foundation 5 slim-lang flash messages helper with devise - ruby-on-rails

I was not able to find many sources that matched my needs out there so I wanted to post this for fellow hackers to chop up and make a bit better. The goal of this helper, was to allow both a list of messages or a single message to be passed to it. This gave me the ability to add all active record failures when saving to the model, or just a generic message any where in my application. I also use rwz/nestive for multiple layouts, and slim-lang for my templates.
Let's start with my flash message partial that allows me to pass a column count to it:
- if flash.present?
div[class="row"]
div[class="large-#{column_count} columns"]
= display_flash_messages(flash)
Which can be called like so:
= render partial: 'partials/flash_message', locals: { column_count: '12'}
The helper code is as follows. Note, I also embed a fontawesome icon before the messages:
module FlashHelper
DEFAULT_KEY_MATCHING = {
alert: {
type: 'alert',
i_class: 'fa fa-exclamation-triangle'
},
notice: {
type: 'success',
i_class: 'fa fa-check'
},
info: {
type: 'standard',
i_class: 'fa fa-check'
},
secondary: {
type: 'secondary',
i_class: 'fa fa-check'
},
success: {
type: 'success',
i_class: 'fa fa-ban'
},
error: {
type: 'alert',
i_class: 'fa fa-exclamation-triangle'
}
}
def display_flash_messages(flash)
html_output = ''
flash.each do |type, message|
key = DEFAULT_KEY_MATCHING[type.to_sym]
alert_wrapper_class = ('alert-box-multiple-wrapper' if message.is_a? Array) || 'alert-box-single-wrapper'
html_output +=
content_tag(:div, class: "alert-box #{key[:type]}", data: { alert: '' } ) do
if message.is_a? Array
html_output_nested =
content_tag(:ul, class: 'alert-box-list') do
message.to_a.map do |list_message|
content_tag(:li, list_message.humanize + '.', class: 'alert-box-li-item')
end.reduce(:<<)
end
else
html_output_nested = content_tag(:span, message.humanize + '.', class: 'alert-box-span-item')
end
html_output_nested = content_tag( :div, html_output_nested, class: "#{alert_wrapper_class}" )
html_output_nested = content_tag(:i, nil, class: "#{key[:i_class]}") + html_output_nested
html_output_nested += link_to('×'.html_safe, '#', class: 'close')
html_output_nested
end
end
raw(html_output)
end
end
The associated SASS:
div.alert-box {
.close {
color: $app-color-code-5;
#include opacity();
}
i {
font-size: 1.3em;
padding: 9px 6px 4px;
line-height: 0;
position: absolute;
top: 50%;
left: 0.5rem;
color: $app-color-code-5;
margin-top: -0.6875rem;
}
div.alert-box-single-wrapper {
margin-left: 25px;
.alert-box-span-item {
font-size: 1em;
}
}
div.alert-box-multiple-wrapper {
ul {
margin-left: 3.7rem;
list-style-type: disc;
margin-bottom: 0;
}
.alert-box-li-item {
font-size: 1em;
}
}
}
In my devise setup, I am now able to use the following. Yes I override the default devise configuration:
if resource_saved
....
else
# merge the ar errors together with devise
if resource.errors.messages.values.flatten.length > 0
flash[:error] = resource.errors.messages.values.flatten
end
# remove passwords from the view layer
clean_up_passwords resource
respond_with resource
end
At the end of the day, this setup builds 2 different sets of html:
<div class="alert-box alert data-alert">
<i class="fa fa-exclamation-triangle"></i>
<div class="alert-box-multiple-wrapper">
<ul class="alert-box-list">
<li class="alert-box-item">The error message.</li>
</ul>
</div>
<a class="close" href="#">×</a>
</div>
<div class="alert-box alert data-alert">
<i class="fa fa-exclamation-triangle"></i>
<div class="alert-box-single-wrapper">
<span class="alert-box-span-item">The error message.</span>
</div>
<a class="close" href="#">×</a>
</div>
Now, all of this works, but I am wondering how others have tackled this problem.

Related

Rails4: Use Coffeescript/javascript variable in view

I'm trying to call a classed coffeescript/javascript function from my Rails 4 view code. It's telling me that the class variable that was created on page load and used in document.ready doesn't exist anymore.
coffeescript:
class App
reload_calendar: ->
source = new Array
viewable_calendars = $('input:checkbox:checked.visable_calendars').map(->
#value
).get().join(',')
calendar_url = '/events.json'
new_event_link = '#{new_event_path}'
$('#calendar').fullCalendar
dayClick: (date, allDay, jsEvent, view) ->
document.location.href = new_event_link + '?start_date=' + date
return
header:
left: 'prev,today,next'
center: 'title'
right: 'month,agendaWeek,agendaDay'
selectable: true
selectHelper: true
editable: false
ignoreTimezone: false
select: #select
eventClick: #eventClick
eventDrop: #eventDropOrResize
eventSources: [ {
url: calendar_url
data:
custom_param1: 'something'
custom_param2: 'somethingelse'
error: ->
alert 'there was an error while fetching events!'
return
} ]
eventResize: #eventDropOrResize
timeFormat: 'h:mmtt{ - h:mmtt} '
return
app = new App
$(document).ready ->
app.reload_calendar()
$('#calendar-color').minicolors()
partial:
<ul>
<% #calendars.each do |c| %>
<li>
<span style="background-color: <%= c.color %>;">
<%= check_box_tag 'show_calendar_'+c.id.to_s, value=c.id.to_s, checked=true, :onchange => "app.reload_calendar()", :class => "visible_calendars" %>
</span>
<%= c.name %>
<%= link_to 'x', calendar_path(c), :confirm => "Are you sure you want to remove the calendar?", :method => :delete %></li>
<% end %>
This loads the calendar fine (using app.reload_calendar at the end of the coffeescript), but fails with the error Uncaught ReferenceError: app is not defined when it's triggered by clicking or unclicking a check_box.
Just use this pattern for each coffescript class
class MyClass
...
root = exports ? window
root.MyClass = MyClass
Some other ways to make your class public here, and here
window.app = new App works, as Long Dương posted in the comments.

Rails and React, how to use helpers and methods?

How to use rails helpers in rails-react? For example, _post.haml partial looks like this
%ul#comments-list.comments-list{:data => { post: post.id }}
%li
.comment-main-level
.comment-avatar
= post_avatar(post)
.comment-box
.comment-head
%h6.comment-name.by-author
= link_to full_name(post.user), post.user
%span="#{post.created_at.strftime("%D:%H:%M:%S")}"
- if user_signed_in?
%i= post_options(post, current_user)
%i=votes(post, current_user, post)
.comment-content
.pop
= check_string(post.content)
= div_for(post.reviews.includes(:user)) do |review|
= render review
= render 'welcome/modal'
I try to put it into react component:
{ div, h2, a, p, input, ul, li, span, h6, img, span } = React.DOM
#Post = React.createClass
render: ->
div {},
ul
className: 'comments-list'
id: 'comments-list'
li null,
div className: 'comment-main-level',
div className: 'comment-avatar',
img
className: 'group-post-img media-object'
src: #props.user.img_url
div className: 'comment-box',
div className: 'comment-head',
h6 className: 'comment-name by-author',
a
href: #props.user.first_name
#props.user.first_name + ' ' +#props.user.last_name
span null, #props.post.created_at
How to realize this part?
- if user_signed_in?
%i= post_options(post, current_user)
%i=votes(post, current_user, post)
This is devise helper, and my own helpers, that contains links (with if else conditions.) I have no idea how to implement this in React. Can anybody tell me how to solve problems like this?
Pass the result of your helper methods as props to your component:
= react_component('Post', {
post: #post,
userSignedIn: user_signed_in?,
postOptions: post_options(post, current_user),
votes: votes(post, current_user, post)
})
In your component use a condition before returning the DOM:
var Post = React.createClass({
render: function() {
var postDetails;
if(this.props.userSignedIn) {
postDetails =
<div className="shown-when-logged-in">
<i>{this.props.postOptions}</i>
<i>{this.props.votes}</i>
</div>
}
return (
<div>
<div className="always-shown">
{this.props.post.content}
</div>
{postDetails}
</div>
);
}
});

Rails ActiveRecord object lookup with dynamically generated content in partial

In my app users have lists and list_items (list_items link the products they add to their appropriate list). I have a product search modal that returns a list of products each with a product_id attribute. I would like to conditionally display a button (either ADD or ADDED) based on whether the user already has the product in their list or not.
The issue is using {raw-product_id} variable that is passed in from the search with the ActiveRecord object lookup. If I manually input an integer, it works fine, but the variable that is used looks like it's a string, and even with to_i appended, doesn't work when using: - if current_user.list_items.where(product_id: '{raw-product_id}'.to_i).exists? Relevant lines of code near the bottom.
code:
-# = form_tag main_app.products_path(), method: :post do
= form_tag main_app.list_items_path, data: { passthru: current_user.nil?, remote: true } do |f|
= hidden_field_tag :success, 'back'
= hidden_field_tag :list_id, args[:list].try(:id) || '0'
.product_picker_inner
.product_picker_body
.product_picker_details
.product_picker_details_default
= hidden_field_tag :product_id, '{raw-product_id}'
= hidden_field_tag :added_from, 'search'
%h4.text-center
{escaped-title}
.text-center.product_picker_category
%span
{escaped-category}
.product_picker_content
.row
.col-xs-12.col-md-6.product_picker_avatar6
%img.img.img-responsive.center-block{ src: '#{raw-avatar}' }
-# .rectangle-avatar.contain-image{ style: 'background-image: url("{encoded-avatar}")' }
.col-xs-12.col-md-6.product_picker_description
{escaped-description}
.col-xs-12.col-md-6
.text-center{ style: 'margin:1em 2em 0.3em 0' }
price:
%b
{raw-price_formatted}
.row{ style: 'padding: 1em 0 0 0;' }
.col-xs-12
.fancy-span{ style: 'font-size: 0.8em' }
%span Tell us about this product
= text_area_tag :comment, '', class: 'form-control'
.text-center.product_picker_controlls
- if current_user.list_items.where(product_id: '{raw-product_id}'.to_i).exists?
= button_tag 'ADDED', type: 'submit', class: 'btn btn-danger btn-lg t03e', id: 'product-{raw-product_id}'
-# %a.btn.btn-primary.btn-lg.t03e{ href: "#{products_path( list_id: args[:list].try(:id) || '0', success: 'back' )}&u={raw-id}", data: { method: :post } }
ADDED
- else
= button_tag 'ADD', type: 'submit', class: 'btn btn-primary btn-lg t03e', id: 'product-{raw-product_id}'
-# %a.btn.btn-primary.btn-lg.t03e{ href: "#{products_path( list_id: args[:list].try(:id) || '0', success: 'back' )}&u={raw-id}", data: { method: :post } }
ADD
.product_picker_loading_overlay
%div{ style: 'position: absolute;top: 50%;left: 0;line-height: 1.1em;right: 0;text-align: center;font-size: 40px;margin: -20px 0 0 0;' }
%i.fa.fa-circle-o-notch.fa-spin
.text-center{ style: '' }
%a{ href: '#', 'data-dismiss' => 'modal' }
CLOSE
In more closely examining the code, I found that there was a javascript file that replaced all instances of {raw-attribute} with the proper values, so this DOM manipulation was not reaching the ERB itself. My solution was to add the button text and button class directly to the JSON itself, and then add those attributes in the HAML.
new json in the jbuilder file:
json.in_list #list.list_items.where(product_id: product[:product_retailer].try(:product_id)).exists? ? 'ADDED' : 'ADD'
json.button_class #list.list_items.where(product_id: product[:product_retailer].try(:product_id)).exists? ? 'btn-danger' : 'btn-primary'
new haml:
.text-center.product_picker_controlls
= button_tag '{raw-in_list}', type: 'submit', class: 'btn btn-lg t03e {raw-button_class}', id: 'product-{raw-product_id}'
-# %a.btn.btn-primary.btn-lg.t03e{ href: "#{products_path( list_id: args[:list].try(:id) || '0', success: 'back' )}&u={raw-id}", data: { method: :post } }
'{raw-in_list}'

ruby on rails qr code implemetation

hi just trying to create a qr code in my rails website using sam vincents qr code generator https://github.com/samvincent/rqrcode-rails3....... first i added this code to a controller
class QrcodeController < ApplicationController
def qrcode
respond_to do |format|
format.html
format.svg { render:qrcode => #qrurl, :level => :l, :unit => 10, :color => black }
format.png { render :qrcode => #qrurl }
format.gif { render :qrcode => #qrurl }
format.jpeg { render :qrcode => #qrurl }
end
end
def options
{:qrcode => "http://helloworld.com", size => 4}
end
end
then i am not sure what to add in the view i tried this
<div class="Qrcode qr">
<h2>Qr code</h2>
<p><%= link_to "SVG", Qrcode_path("svg") %></p>
<p><%= link_to "PNG", Qrcode_path("png") %></p>
<p><%= link_to "JPEG", Qrcode_path("jpeg") %></p>
<p><%= link_to "GIF", Qrcode_path("gif") %></p>
would appreciate any help on how it works as their are not that many instructions online
im using ruby 1.9.3 and rails 4.0.1
I'm using rqrcode gem. It's pretty simple and you don't need to generate images for your qrcodes. The code is generated using tables and some css styles...
You can use this helper: /helpers/qrcode_helper.rb
module QrcodeHelper
require 'rqrcode'
def render_qr_code text, size = 3
return if text.to_s.empty?
qr = RQRCode::QRCode.new(text)
sizeStyle = "width: #{size}px; height: #{size}px;"
content_tag :table, class: "qrcode pull-right" do
qr.modules.each_index do |x|
concat(content_tag(:tr) do
qr.modules.each_index do |y|
color = qr.dark?(x, y) ? 'black' : 'white'
concat content_tag(:td, nil, class: color, style: sizeStyle)
end
end)
end
end
end
end
Into your view some_view.html.erb
<%= render_qr_code("MYCODE") %>
And you need to add style for your code qrcode.css.less
table.qrcode {
border-width: 0;
border-style: none;
border-color: #0000ff;
border-collapse: collapse;
margin-top: 100px;
margin-bottom: 12px;
td {
border-width: 0;
border-style: none;
border-color: #0000ff;
border-collapse: collapse;
padding: 0;
margin: 0;
width: 3px;
height: 3px;
&.black {
background-color: #000 !important
}
&.white {
background-color: #fff !important
}
}
}
My example it's working with Rails 3.
Here's a minimal example that avoids the need to write code to render each (x,y) "pixel" yourself.
In your controller:
def show
#qr = RQRCode::QRCode.new('https://stackoverflow.com/')
end
And then in your corresponding .html.erb view:
<p>
<%== #qr.as_svg %>
</p>
(Note that this uses <%==, not <%=; if you use the latter, you'll get the raw SVG XML source instead of a rendered SVG image.)
See the RQRCode docs for options that can be passed to .as_svg, and for other output options such as PNG.

time_select blank field saves a default time when form is submitted

Im having trouble understanding my options for time_select. My goal is to have only user created time selections render in my show action after form submission.
What is happening however is a default time of 12:00 AM being rendered for all time_select fields not touched by a user. I am looking for a way to either stop default time values from saving (which if I had to guess, isn't possible), or create a conditional that would allow me to prevent default time values from rendering.
I have looked over the following with no success so far:
Nil value on datetime_select?
Optional time_select with allow_blank defaults to 00:00
Rails time_select set default
Rails 3: How to prevent my validations to pass a "nil time" from time_select dropdowns?
http://api.rubyonrails.org/classes/ActionView/Helpers/DateHelper.html#method-i-time_select
Here is my code:
_form.html.erb (only the snippet that I am having trouble with for brevity)
<td>
<span style="display: block; width: auto; margin-left: 4%">
<%= f.time_select :med1_time_of_day1, { include_blank: true, twelve_hour: true, minute_step: 15, ampm: true }, style: "width: 45%;" %>
</span>
<span style="display: block; width: auto; margin-left: 4%">
<%= f.time_select :med1_time_of_day2, { include_blank: true, twelve_hour: true, minute_step: 15, ampm: true }, style: "width: 45%;" %>
</span>
<span style="display: block; width: auto; margin-left: 4%">
<%= f.time_select :med1_time_of_day3, { include_blank: true, twelve_hour: true, minute_step: 15, ampm: true }, style: "width: 45%;" %>
</span>
<span style="display: block; width: auto; margin-left: 4%">
<%= f.time_select :med1_time_of_day4, { include_blank: true, twelve_hour: true, minute_step: 15, ampm: true }, style: "width: 45%;" %>
</span>
</td>
<td>
show.html.erb
<table class="table table-bordered table-striped">
<thead>
<th>Medication Name & Instructions for Use</th>
<th>Time of Day</th>
<th>
Day(s) of the Month Medication was Taken
</th>
</thead>
<tbody>
<td>
<%= #med_record_form.med1_name %>
<%= #med_record_form.med1_instruct %>
</td>
<td>
<% unless #med_record_form.med1_time_of_day1.nil? %>
<%= #med_record_form.med1_time_of_day1.strftime("%I:%M %p") %>
<br />
<% end %>
<% unless #med_record_form.med1_time_of_day2.nil? %>
<%= #med_record_form.med1_time_of_day2.strftime("%I:%M %p") %>
<br />
<% end %>
<% unless #med_record_form.med1_time_of_day3.nil? %>
<%= #med_record_form.med1_time_of_day3.strftime("%I:%M %p") %>
<br/>
<% end %>
<% unless #med_record_form.med1_time_of_day4.nil? %>
<%= #med_record_form.med1_time_of_day4.strftime("%I:%M %p") %>
<br />
<% end %>
</td>
</tbody>
</table>
Note: I've also tried replacing #instance_var.nil? with
#instance_var.blank? and #instance_var.empty? without success.
And just in case the controller is needed...
med_record_forms_controller.rb
class MedRecordFormsController < ApplicationController
before_filter :get_resident
def index
#med_record_form = #resident.med_record_forms
end
def new
#med_record_form = #resident.med_record_forms.build
end
def create
#med_record_form = #resident.med_record_forms.build(params[:med_record_form])
if #med_record_form.save
redirect_to [#resident, #med_record_form] #, flash_class[:success] = "Form was created!"
else
render 'new' #, flash[:error] = "There was a problem with the form"
end
end
def show
#med_record_form = #resident.med_record_forms.find(params[:id])
end
def update
#med_record_form = #resident.med_record_forms.find(params[:id])
if #med_record_form.update_attributes(params[:med_record_form])
flash[:success] = "Form updated"
redirect_to controller: 'residents', action: 'show', id: params[:id]
else
render 'edit', flash[:error] = "Unable to update form"
end
end
def edit
#med_record_form = #resident.med_record_forms.find(params[:id])
end
def destroy
#med_record_form = #resident.med_record_forms.find(params[:id])
#med_record_form.destroy
flash[:notice] = "You sure?"
redirect_to resident_med_record_forms_path
end
private
# get_resident converts the resident_id given by the routing
# into an #resident object, for use in this controller & coresponding views
def get_resident
#resident = Resident.find(params[:resident_id])
end
end
This question is similar to this: Optional time_select with allow_blank defaults to 00:00
I found the default for time_select sets the time parts blank but there is a hidden date component that is not set to blank. You can see this when you look at the parameters:
"my_time(1i)"=>"1", "my_time(2i)"=>"1", "my_time(3i)"=>"1", "my_time(4i)"=>"", "my_time(5i)"=>""
You will need to set the time to nil in your controller like this:
def create
#med_record_form = #resident.med_record_forms.build(params[:med_record_form])
#med_record_form.med1_time_of_day1 = nil if params[:med_record_form]["med1_time_of_day1(4i)"].blank? &&
params[:med_record_form]["med1_time_of_day1(5i)"].blank?
if #med_record_form.save
redirect_to [#resident, #med_record_form] #, flash_class[:success] = "Form was created!"
else
render 'new' #, flash[:error] = "There was a problem with the form"
end
end

Resources