Rails: how to output pretty html? - ruby-on-rails

I use SASS as views engine with built-in prettyfying option in config/application.rb:
Slim::Engine.set_default_options :pretty => true
Nevertheless, not only usage of rdiscount for posts rendering breaks all that beauty, but typical commands do that, e.g.:
title
= "#{t "title.main"} - #{(yield :title) || "#{t "title.default"}"}"
== stylesheet_link_tag "application", :media => "all"
turns into
<title>Some title</title><link href="/assets/application.css?body=1" media="all" rel="stylesheet" type="text/css" />
In additon, some examples of tags indentation:
<body>
<header>
<h1>...
</header>
<div class="content"><div class="posts"><article>
<div class="title">
<h3>...</h3>
<h2>...</h2>
</div>
<div class="entry"><p>...</p>
<p>...</p>
</div>
</article><article>
<div class="title">
<h3>...</h3>
<h2>...</h2>
</div>
<div class="entry"><p>...</p>
<p>...</p>
</div>
</article><article>
Maybe there is some after_filter or whatever exist to prettify responce.body after all?
That :pretty => true will be disabled then because it does only a half of the work.

Related

Google maps autocomplete js is working on localhost but not on heroku

I'm a junior ruby on rails developer. I developed a web app that uses Google maps javascript API and I use the autocomplete function on a form input.
The autocomplete works fine on localhost but does not work anymore after deploying on heroku.
Here is my html.erb below. For your perfect information, the form is in the page footer. This form is partially hidden and the only visible part corresponds to a button used to upload a video file. Once this button has been clicked and the video file has been chosen, I display a modal containing the rest of the form. That's where the 'text_field_tag' (with the id = "user_input_autocomplete_address") is displayed and where the autocomplete should work.
<% if user_signed_in? %>
<div class="footer-check hidden-md hidden-lg">
<div class="container text-right">
<div class="row">
<div class="flexbox">
<div class="footer-home active">
<%= link_to root_path do %>
<i class="fa fa-home" aria-hidden="true"></i>
<% end %>
</div>
<div class="footer-search">
<!-- later put link_to reviews_path -->
<%= link_to search_path do %>
<i class="fa fa-search" aria-hidden="true"></i>
<% end %>
</div>
<div class="footer-button">
<%= simple_form_for(Review.new) do |f| %>
<div id="add_video_image_btn">
<label for="review_video", class="add_video_image"><%= image_tag "plus.png" %></label>
<%= f.input :video, label: false, input_html: { accept: ".mp4, .mov, .m4v, .wmv, .webm, .avi", class: 'hidden'} %>
<%= f.input :video_cache, as: :hidden, class: "add_video_image file required" %>
</div>
</div>
<div class="footer-likes">
<%= link_to dashboard_users_path do %>
<i class="fa fa-heart" aria-hidden="true"></i>
<% end %>
</div>
<div class="footer-user">
<%= link_to user_path(current_user) do %>
<i class="fa fa-user" aria-hidden="true"></i>
<% end %>
</div>
</div>
</div>
</div>
</div>
<!--Beginning Modal -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-body">
<div id="add_video_form_step2">
<%= f.error_notification %>
<fieldset class="form-group" style="margin-bottom:0;">
<div class="section">
Place
</div>
<div class="inner-wrap">
<div id="">
<%= text_field_tag :place, nil, class: 'form-control', id: 'user_input_autocomplete_address', placeholder: 'Start typing...', size: 80 %>
</div>
</div>
<div class="section">
Comment
</div>
<div class="inner-wrap">
<%= text_field_tag :comment, nil, class:'form-control', placeholder: 'Food is good but the place is a bit noisy', size: 80 %>
</div>
<div class="inner-wrap" style="padding:15px;">
<div class="emoji-toggle emoji-happy">
<input type="checkbox" id="toggle1" class="toggle" name="review[mood]" value="false">
<div class="emoji"></div>
<label for="toggle1" class="well"></label>
</div>
</div>
<div class="">
<%= f.button :submit, class: "btn btn-primary form-control", id: "click-trigger" %>
</div>
<%= hidden_field_tag :name, id: 'name' %>
<%= hidden_field_tag :street_number, id: 'street_number' %>
<%= hidden_field_tag :route, id: 'route' %>
<%= hidden_field_tag :locality, id: 'locality' %>
<%= hidden_field_tag :administrative_area_level_1, id: 'administrative_area_level_1' %>
<%= hidden_field_tag :postal_code, id: 'category_0' %>
<%= hidden_field_tag :country, id: 'country' %>
<%= hidden_field_tag :formatted_address, id: 'formatted_address' %>
<%= hidden_field_tag :phone_number, id: 'phone_number' %>
<%= hidden_field_tag :website, id: 'website' %>
<%= hidden_field_tag :gplace_id, id: 'gplace_id' %>
<%= hidden_field_tag :category_0, id: 'category_0' %>
<%= hidden_field_tag :category_1, id: 'category_1' %>
<%= hidden_field_tag :category_2, id: 'category_2' %>
<%= hidden_field_tag :category_3, id: 'category_3' %>
<%= hidden_field_tag :category_4, id: 'category_4' %>
<%= hidden_field_tag :category_5, id: 'category_5' %>
<%= hidden_field_tag :hours_open_day_0, id: 'hours_open_day_0' %>
<%= hidden_field_tag :hours_open_day_1, id: 'hours_open_day_1' %>
<%= hidden_field_tag :hours_open_day_2, id: 'hours_open_day_2' %>
<%= hidden_field_tag :hours_open_day_3, id: 'hours_open_day_3' %>
<%= hidden_field_tag :hours_open_day_4, id: 'hours_open_day_4' %>
<%= hidden_field_tag :hours_open_day_5, id: 'hours_open_day_5' %>
<%= hidden_field_tag :hours_open_day_6, id: 'hours_open_day_6' %>
</fieldset>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<% end %>
<% end %>
<!--End Modal -->
<!-- Start of js to display the modal -->
<!-- NB: the autocomplete module is in assets/javascript/autocomplete.js -->
<%= content_for :after_js do %>
<script>
$('#review_video').change(function(){
$('#myModal').modal('show');
});
</script>
<% end %>
<!-- End of js to display the modal -->
The footer (gathering the modal and the form) is called within a layouts/application.html.erb view, which is below. You'll see that I use Google API key in there (hidden in application.yml)
<!DOCTYPE html>
<html>
<head>
<title><%= meta_title %></title>
<%= csrf_meta_tags %>
<!-- Start Favicon -->
<%= favicon_link_tag '_/app/assets/images/favicon.ico' %>
<link rel="manifest" href="/manifest.json">
<meta name="msapplication-TileColor" content="#ffffff">
<meta name="msapplication-TileImage" content="<%= image_path 'ms-icon-144x144.png' %>">
<meta name="theme-color" content="#ffffff">
<!-- end Favicon -->
<meta name="description" content="<%= meta_description %>">
<!-- Facebook Open Graph data -->
<meta property="og:title" content="<%= meta_title %>" />
<meta property="og:type" content="website" />
<meta property="og:url" content="<%= request.original_url %>" />
<meta property="og:image" content="<%= meta_image %>" />
<meta property="og:description" content="<%= meta_description %>" />
<meta property="og:site_name" content="<%= meta_title %>" />
<!-- Twitter Card data -->
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:site" content="<%= DEFAULT_META["twitter_account"] %>">
<meta name="twitter:title" content="<%= meta_title %>">
<meta name="twitter:description" content="<%= meta_description %>">
<meta name="twitter:creator" content="<%= DEFAULT_META["twitter_account"] %>">
<meta name="twitter:image:src" content="<%= meta_image %>">
<!-- Google+ Schema.org markup -->
<meta itemprop="name" content="<%= meta_title %>">
<meta itemprop="description" content="<%= meta_description %>">
<meta itemprop="image" content="<%= meta_image %>">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<link rel="apple-touch-icon" sizes="152x152" href="/apple-icon-152x152.png">
<%= stylesheet_link_tag 'application', media: 'all' %>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<!-- start Mixpanel -->
<script type="text/javascript">(function(e,b){if(!b.__SV){var a,f,i,g;window.mixpanel=b;b._i=[];b.init=function(a,e,d){function f(b,h){var a=h.split(".");2==a.length&&(b=b[a[0]],h=a[1]);b[h]=function(){b.push([h].concat(Array.prototype.slice.call(arguments,0)))}}var c=b;"undefined"!==typeof d?c=b[d]=[]:d="mixpanel";c.people=c.people||[];c.toString=function(b){var a="mixpanel";"mixpanel"!==d&&(a+="."+d);b||(a+=" (stub)");return a};c.people.toString=function(){return c.toString(1)+".people (stub)"};i="disable time_event track track_pageview track_links track_forms register register_once alias unregister identify name_tag set_config reset people.set people.set_once people.increment people.append people.union people.track_charge people.clear_charges people.delete_user".split(" ");
for(g=0;g<i.length;g++)f(c,i[g]);b._i.push([a,e,d])};b.__SV=1.2;a=e.createElement("script");a.type="text/javascript";a.async=!0;a.src="undefined"!==typeof MIXPANEL_CUSTOM_LIB_URL?MIXPANEL_CUSTOM_LIB_URL:"file:"===e.location.protocol&&"//cdn.mxpnl.com/libs/mixpanel-2-latest.min.js".match(/^\/\//)?"https://cdn.mxpnl.com/libs/mixpanel-2-latest.min.js":"//cdn.mxpnl.com/libs/mixpanel-2-latest.min.js";f=e.getElementsByTagName("script")[0];f.parentNode.insertBefore(a,f)}})(document,window.mixpanel||[]);
mixpanel.init("ENV['MIXPANEL_TOKEN']");
</script>
<!-- end Mixpanel -->
</head>
<body>
<%= render 'shared/flashes' %>
<%= yield %>
<%= render 'shared/footer' %>
<%= javascript_include_tag "http://maps.google.com/maps/api/js?libraries=places&key=#{ENV['GMAP_BROWSER_KEY']}" %>
<%= javascript_include_tag "http://cdn.rawgit.com/mahnunchik/markerclustererplus/master/dist/markerclusterer.min.js" %>
<%= javascript_include_tag 'application' %>
<%= yield :after_js %>
</body>
</html>
Last, the javascript code allowing the autocomplete on the input (having "user_input_autocomplete_address" as id) is in assets/javascript/autocomplete.js and is the following :
function initializeAutocomplete(id) {
var element = document.getElementById(id);
console.log('coucou');
if (element) {
var autocomplete = new google.maps.places.Autocomplete(element, { types: ['geocode', 'establishment'] });
google.maps.event.addListener(autocomplete, 'place_changed', onPlaceChanged);
}
}
function onPlaceChanged() {
var place = this.getPlace();
console.log(place); // Uncomment this line to view the full object returned by Google API.
for (var i in place.address_components) {
var component = place.address_components[i];
// console.log(component.types);
for (var j in component.types) { // Some types are ["country", "political"]
var type_element = document.getElementById(component.types[j]); // Returns the div with their differents ids or null if the id doesnt exist
// console.log(document.getElementById(component.types[j]));
if (type_element) {
type_element.value = component.long_name;
}
}
}
var formatted_address = document.getElementById('formatted_address');
// console.log(international_phone_number);
if (formatted_address) {
formatted_address.value = place.formatted_address;
}
for (var i in place.types) {
// console.log(place.types);
// console.log(i);
// console.log(place.types[i]);
var type_content = document.getElementById('category_' + i); // Returns the div with their differents ids or null if the id doesnt exist
// console.log(document.getElementById(component.types[j]));
if (type_content) {
console.log(place.types[i]);
type_content.value = place.types[i];
}
}
var international_phone_number = document.getElementById('phone_number');
// console.log(international_phone_number);
if (international_phone_number) {
international_phone_number.value = place.international_phone_number;
}
var name = document.getElementById('name');
if (name) {
name.value = place.name;
}
var gplace_id = document.getElementById('gplace_id');
if (gplace_id) {
gplace_id.value = place.place_id;
}
var website = document.getElementById('website');
if (website) {
website.value = place.website;
}
for (var i in place.opening_hours.weekday_text) {
var hours_open_in_db = place.opening_hours.weekday_text[i];
var hours_open_in_form = document.getElementById('hours_open_day_' + i);
if (hours_open_in_form) {
hours_open_in_form.value = hours_open_in_db;
}
}
}
google.maps.event.addDomListener(window, 'load', function() {
initializeAutocomplete('user_input_autocomplete_address');
});
In order to deploy all this on heroku, I already did the following :
"heroku run db:migrate" in the terminal (because I had some pending
migrations);
"figaro heroku:set -e production" in the terminal, in order to push all my API keys to heroku (I also checked that these keys are indeed in heroku's config vars).
in Google's developer console, within my project and within Google map javascript API, I ensured that my browser key is allowed for both my locahost and my domain name. In order to be very precise, I am using the same key for my locahost and my domain name. Until now, the only thing I have not managed to do yet, in Google's console, is to prove that I own my domain name.
I checked I have not reached any of my API quotas yet.
Within my autocomplete.js file, I used some console.log in order to find out, in my browser's inspector, what parts of the code are working. It seems that everything works except the console.logs that are in the 'OnPlaceChange' callback, since Gmap's autocomplete suggestions are not shown... ;
I know that not seeing the autocomplete suggestions is not a problem of z-index associated to the .pac-container css element, since I already had to fix this and since Gmaps suggestions cannot be reached thanks to my keyboard arrows.
I read this post about geocomplete (geocomplete for rails 4 not working in Heroku) and tried to precompile my assets. That did not lead to any change.
In my browser inspector (in the 'network' section), when I write something in my form input, every new letter pressed on the keyboard triggers a new request. These requests names are 'AutocompletionService.GetPredictions.....'. In the "headers" section, I can see they are https requests to googleapis, with get methods and 200 status code. In the "response" section, I can see there seems to be a error with my API keys since the message is :
/**/_xdc_._ty4oqn && _xdc_._ty4oqn( [3,null,null,"This API project is not authorized to use this API. Please ensure that this API is activated in the APIs Console: https://console.developers.google.com/apis/library?project=_ Please ensure this API is activated in the Google Developers Console: https://console.developers.google.com/apis/api/places_backend?project=_ For more information on authentication and Google Maps Javascript API services please see: https://developers.google.com/maps/documentation/javascript/get-api-key"] )
I followed the link in the error message, leading me to Google's console, and I get back to my project and API keys, which are settled both server-side and browser-side. Once again, the only thing i did not managed to do in Google's console was to prove I own my domain name.
Is this last point the origin of the issue (and in this case I guess I need some help from my hosting services) or do you guys see another mistake?
I has same issue too.
just goto google console, enable the "Google Places API Web Service", then it will solved the problem.
Enable "Google Places API Web Service" on Google API Console. It solved my problem when the website worked on localhost, but don't at Locaweb server.

Creating another layout template for a Site made with Ruby on Rails

I'm trying to create two separate layout templates in ruby because everything is defaulting to the application.html.er layout, but I can't seem to get it right. Ive tried about 5 solutions on here and none of them seem to work for my code. Please someone help?
app/controllers/pages_controller.rb :
`
class PagesController < ApplicationController
def home
layout :homeLayout_layout
end
end
`
views/layouts/homeLayout.html.erb:
`
<!DOCTYPE html>
<html>
<head>
<title>Checklance</title>
<%= stylesheet_link_tag "//netdna.bootstrapcdn.com/bootstrap/3.0.0-rc1/css/bootstrap.min.css", "application", media: "all", "data-turbolinks-track" => true %>
<%= javascript_include_tag "//netdna.bootstrapcdn.com/bootstrap/3.0.0-rc1/js/bootstrap.min.js", "application", "data-turbolinks-track" => true %>
<%= csrf_meta_tags %>
<link href='http://fonts.googleapis.com/css?family=Poiret+One' rel='stylesheet' type='text/css'>
<link href='http://fonts.googleapis.com/css?family=Changa+One' rel='stylesheet' type='text/css'>
<link href='http://fonts.googleapis.com/css?family=Open+Sans+Condensed:300' rel='stylesheet' type='text/css'>
<style type="text/css">
body {
padding-top: 50px;
}
</style>
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top" id="navbar">
<div class="container" id="body">
<a id="nav" class="navbar-brand" href="/projects">
<img src="http://i1051.photobucket.com/albums/s423/Kira-Banks/check-2.png" id="logo">
Checklance
</a>
</div>
</div>
<div class="container" id="homeContainer">
<%= yield %>
</div>
<footer id="footer">Copyright 2014 Kira Banks</footer>
</body>
</html>
`
views/pages/home.html.erb :
`
<h1 id="homeTitle">Welcome!</h1>
`
Thanks in advance!
Your file names should all be snake_case in Rails. Change views/layouts/homeLayout.html.erb to views/layouts/home_layout.html.erb and your controller should look like:
class PagesController < ApplicationController
def home
render layout: "home_layout"
end
end
Also you can mention the newly created layout top of the controller. So, that will be effective in all action's of the respective controller and your controller should look like:
class PagesController < ApplicationController
layout: "home_layout"
def home
end
end

How to add a full background-color to a div?

I have a ruby on rails app, and I'd like to put a full width background-color to a div, but without success, everytime I have unwanted left-right and top margin.
Here is my code:
<!DOCTYPE html>
<html lang="en">
<!-- header -->
<body>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<div class="homepage">
<div class="container center">
<div class="texthomepage1">
<br>
<font color="white"><p>Découvrez des startups</p></font>
</div>
<div class="texthomepage2">
<p><font color="white">Faites les découvrir à vos amis & obtenez des récompenses.</font></p></font>
</div>
<br><br><br>
<center>
<!-- REGISTRATION FIELDS -->
<div class="panel-body">
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<div class="form-group">
<%= link_to "Rejoindre Gratuitement", new_user_registration_path, class: "btn btn-lg btn-info" %>
<% end %>
<!-- /REGISTRATION FIELDS -->
<br><br><br>
</div>
</div>
</center>
</div>
</div>
Here is my css for the .homepage div:
.homepage {
background-color: #e4685d;
margin: 0
}
But with that code I stil have a margin, so the background color doesn't cover the full background.
What could be the right way to do this ?
Make sure your body class doesn't have padding and margins
body{padding:0;margin:0;}
.homepage {
background-color: #e4685d;
margin: 0;
}
Try:
body{
margin:0;
}
Also, your <meta />, <style> or <link> tags should be inside a <head> tag. Notice that your <meta /> tag is in your <body>.

gmaps4rails on jQueryMobile map not showing when redirecting

I am using gmap4rails on jQueryMobile but the map is not showing when I'm doing a redirecting to the page showing the map. The map shows normally when I refresh the map page, but not when I redirect to the page showing the page. Does anyone have an idea why? Thanks! Below is the code
/app/views/items/map.html.erb
<div data-role="header">
<h1>Market</h1>
<%= link_to 'Sell/Buy', new_item_path, "data-icon" => "plus", "class" => "ui-btn-right" %>
<%= link_to 'Back', root_path, "class" => "ui-btn-left" %>
</div>
<div class="center-wrapper">
<div data-role="controlgroup" data-type="horizontal">
List
Map
</div>
</div>
<div data-role="content">
<%= gmaps4rails(#json) %>
</div>
/app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
<head>
<title>Project</title>
<%= stylesheet_link_tag "application", :media => "all" %>
<link rel="stylesheet"
href="http://code.jquery.com/mobile/1.3.1/jquery.mobile-1.3.1.min.css" />
<%= javascript_include_tag "application" %>
<script src="http://code.jquery.com/mobile/1.3.1/jquery.mobile-1.3.1.min.js"></script>
<meta name="viewport" content="initial-scale=1, maximum-scale=1">
<%= csrf_meta_tag %>
</head>
<body>
<div data-role="page">
<%= yield %>
<%= yield :scripts %>
</div>
</body>
</html>
/config/routes.rb
ProjectZ::Application.routes.draw do
...
match '/map', to: 'items#map'
end

Closing Flash Notice Causes page to redirect

I am following the tutorial for devise and cancan integration for rails.
https://github.com/RailsApps/rails3-bootstrap-devise-cancan
I notice when a user logs in the flash notice causes the page to reload after it has been closed out.
I see this in my logs: Redirected to "the root path" Completed 302
here is my routes file
App::Application.routes.draw do
resources :videos do
collection do
post "delete_selected_item"
end
end
unauthenticated do
root :to => 'external#index'
match '/features' => 'external#features'
match '/pricing' => 'external#pricing'
end
devise_scope :user do
match '/sign_up' => 'devise/registrations#new'
match '/sign_in' => 'devise/sessions#new'
end
devise_for :users
authenticated :user do
root :to => "dashboard#index"
match 'dashboard/videos' => 'videos#index'
match 'dashboard/statistics' => 'statistics#index'
match 'dashboard/analytics' => 'analytics#index'
resources :users
end
post "zencoder-callback" => "zencoder_callback#create", :as => "zencoder_callback"
end
layout code:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><%= content_for?(:title) ? yield(:title) : "BriteVid" %></title>
<meta name="description" content="<%= content_for?(:description) ? yield(:description) : "BriteVid" %>">
<meta name="csrf-token" content="<%= form_authenticity_token %>" />
<meta name="csrf-param" content="authenticity_token" />
<%= stylesheet_link_tag "application", :media => "all" %>
<link href="https://vjs.zencdn.net/4.0/video-js.css" rel="stylesheet">
<script src="https://vjs.zencdn.net/4.0/video.js"></script>
<%= javascript_include_tag "application" %>
<link href="<%= image_path("favicon.ico") %>" rel="shortcut icon" />
<%= csrf_meta_tags %>
<%= yield(:head) %>
</head>
<body class="<%=params[:controller].parameterize%> <%=params[:action].parameterize%>">
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="navbar-inner">
<div id="nav_header">
<%= render 'dashboard/internal_header' %>
</div>
</div>
</div>
<%= render 'layouts/shared/alerts' %>
<div id="wrap">
<div id="main" role="main">
<%= render 'dashboard/dashnav' %>
<%= yield %>
<% if Rails.env.production? %> <%= render 'layouts/shared/ga' %><% end %>
</div>
</div>
<%= render 'layouts/shared/chat' %>
</body>
</html>
Flash Message Code
<div class="container">
<% if user_signed_in? %>
<% flash.each do |name, msg| %>
<div class="alert-<%= name == :notice ? "success" : "error" %> fade in">
<a class="close" data-dismiss="alert" href="">x</a>
<center><%= content_tag :div, msg, :id => "flash_#{name}" %></center>
</div>
<% end %>
<% end %>
</div>
Do you shure that you correctly include bootstrap javascript files?
In application.js should be that line:
//= require bootstrap
Change this
<a class="close" data-dismiss="alert" href="">x</a>
to this
<a class="close" data-dismiss="alert" href="#">x</a>
Now, the page will no longer redirect to root url.
[edit]
an empty href="" in <a> tag reloads the page. so, you can change it to the following:
href="#" adds an extra entry to the browser history (which is annoying when e.g. back-buttoning).
href="javascript:;" does not seem to have any problems (other than looking messy and meaningless)

Resources