Am I loading scripts correctly in sinatra? - ruby

I have never done anything in sinatra before and decided to try it out on a project. I am confused on how script loading works. It seems to be intermittently working. Sometimes 2 scripts/css files will have internal server errors, and sometime they will all have errors.
This is my layout.erb :
<!doctype html>
<html>
<head>
<title>An HTML5 box of sand</title>
<meta charset="utf-8" />
<link href='http://fonts.googleapis.com/css?family=Arvo' rel='stylesheet' type='text/css'>
<link rel="stylesheet/less" type="text/css" href="/assets/stylesheets/style.less">
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script><!--loads jquery-->
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.min.js"></script><!--loads jquery ui-->
<script type="text/javascript" src="/assets/js/lib/handlebars.js"></script>
<script src="/assets/js/lib/less-1.3.0.min.js" type="text/javascript"></script>
<script type="text/javascript" src="/assets/js/script.js"></script><!--This is the place where you play!!!-->
</head>
<body>
<%= yield %>
</body>
</html>
I have the assets folder inside of the public folder /public/assets. It is weird because sometimes it will load the assets/js/script.js file, and not load the handlebars file. Other times it will load the handlebars and not the script.js file. I am not sure what is going on.
~~~~~~~~~~~~~~~~~UPDATE~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Discovered the problem but don't know how to fix it.
So, it seems that because I am using data mapper the auto_migrate! method is somehow screwing with how the assets are being loaded. Is there something I can do about this. Here is what I have in my app.rb file:
require 'rubygems'
require 'sinatra'
require 'data_mapper'
# Include the models
require './models/User'
# Connect to mysql
DataMapper.setup(:default, "mysql://root#localhost/dev_landing")
#This line is what is messing everything up.
DataMapper.auto_migrate!
set :public_folder, 'public'
get '/' do
erb :home
end
I set up data mapper like this because I read in a tutorial that this is how you get it to automatically create the tables you specify in your models. Is there a better way to do this so that it is not messing up the loading of my scritps and css?

DataMapper.auto_migrate! deletes existing tables in case they exist and creates them again.
So calling this function means: you lose all your data. (That's why there is an exclamation mark at the end, meaning: watch out!) In case your schema is still under heavy development, I suggest you to replace DataMapper.auto_migrate! by DataMapper.auto_upgrade!. It does not wipe your old data, instead it tries to modify the underlying tables while trying to keep the data. The exclamation mark is still there because your data might still get slightly damaged because changing the schema without corrupting the data is not always possible.
Another thing, the order of calls must be changed. Currently it is:
Model definitions
DataMapper.Setup
DataMapper.auto_migrate!
Your route definitions etc.
But it should be instead:
DataMapper.Setup
Model definitions
DataMapper.auto_migrate! DataMapper.auto_upgrade!
DataMapper.finalize (you forgot that one)
Your route definitions etc.
When something is screwed up with datamapper, the error messages can be weird/misleading. By the way, make sure that there are no calls to the database from inside your views. These calls belong into the controller, without any exception in my opinion. This way your app naturally follows the MVC pattern. (After all Sinatra hardly enforces any other structure... ;))

Related

Thymeleaf ${#request.requestURI} returns a double value

So I have this template in Thymeleaf:
<script th:src="#{|${#request.requestURI}ace-builds/src-noconflict/ace.js|}" type="text/javascript" charset="utf-8"></script>
What I want it to do is pull the current directory(?) it's in, and attach it to the front of the source. So if this is on the page www.mywebsite.com/mypage, it will generate the source tag /mypage/ace-builds/src-noconflict/ace.js.
From other posts here, it looks like that's what should happen, for me, I get this instead:
/mypage/mypage/ace-builds/src-noconflict/ace.js
I can't for the life of me figure out why this is happening. For those wondering why I'd want to do this in the first place, this program is running out of a WAR on a tomcat 9 server, and so the source tag needs to include the mypage war file name to pull from it, which I can hardcode to make work, and I can't pull static resources with just /ace-builds/src-noconflict/ace.js.
Never mind, I am a fool and missed the advise in one of the threads I was checking. Just needed to use:
<script th:src="#{ace-builds/src-noconflict/ace.js}" type="text/javascript" charset="utf-8"></script>
I was trying regular src before, without thymeleaf, and thought the leading / was necessary. Not the case.

Templating in Polymer: How to load components into a specific layout

I am coming from a PHP/Laravel direction and there we use the blade templating engine to load components into a specific layout like this:
Main Layout called: layout.blade.php
<html>
<head><title>Whatever</title></head>
<body>
#yield('content')
</body>
And then we load our components inside this layout by a file like this, called: content.php
#extends(layout)
#section('content')
<h1>This contents is loaded into the Layout</h1>
<p>Yada yada yada</p>
#stop
In the backend we link the route (lets call it "/content") to a controller that creates this view. And anytime we click on a menu-item with an anchor-tag, we load the views into our layout.
Now with Polymer, this is a different story, because I have no Idea how to go on about.
A layout in polymer looks more like this. Let's call this layout-one.html
<html>
<head><title>Whatever</title></head>
<body>
<core-drawer-panel>
<core-header-panel drawer></core-header-panel>
<core-header-panel content>
<core-toolbar main></core-toolbar>
<div>Main Content goes here...</div>
</core-header-panel>
</core-drawer-panel>
</body>
</html>
It's something like that, I know the structure above might have a mistake, but I am pulling this information out of my head.
Now if I have a different view I want to load inside the "content"-Area, intuitively I would have an achor-tag that loads a "content.html", which in turn would have to have all the html-tags and head-tags and so on... so I would load the complete page, which is counter-intuitive and non-dynamic.
I've seen the Polymer-Team accomplish, what I am trying to accomplish here:
http://www.polymer-project.org/components/core-elements/demo.html#core-scroll-header-panel
Just loading different contents into an existing polymer-layout.
So please in the name of god, can anyone tell me exactly how it is done, because I seriously have no idea at the moment. I am suggesting, that they used something like angular to create the views (because of the hash-tag), but my instinct says, that they made it somehow else.
I would be most glad, if you gave me besides the explanation on how it is done, also any resource on how I would be reproduce this behaviour. Maybe a good article or tutorial.
Thanks mates.
You're looking for the <content> tag. Check out how this works.
simple-layout.html
<polymer-element name="simple-layout" noscript>
<template>
<core-drawer-panel>
<core-header-panel drawer>
<content select=".title"><!-- content with class 'title' --></content>
</core-header-panel>
<core-header-panel content>
<core-toolbar main></core-toolbar>
<content><!-- all other content will show up here --></content>
</core-header-panel>
</core-drawer-panel>
</template>
</polymer-element>
home-page.html
<link rel="import" href="simple-layout.html">
<polymer-element name="home-page" noscript>
<template>
<simple-layout>
<div class="title">Home</div>
<h1>This contents is loaded into the main part of the layout.</h1>
<p>Yada yada yada. More content in the main layout.</p>
</simple-layout>
</template>
</polymer-element>
This way you can load a "page" element and it will include the layout it wants to use.
http://erikringsmuth.github.io/app-router/#/layouts

HAML layout.haml and Sinatra not working with url parameters

My index.haml is working fine with, for example:
get '/about' do
haml :about
end
But if I try to use a user parameter like:
get ':user/add' do
haml :add_item
end
The layout.haml is ignored.
I was trying to get this to work using subdirectories in my view folder like:
/view/contact/add.haml
While it inserts the =yield content, it will not show the layout.haml css styles, etc.
So I thought using subdirectories was the issue and put all my hamls in the base views directory. However it seems that anything using a url parameter like get ':user/add' does not incude the layout.haml regardless. Currently this is a test I did:
myapp.rb
require "rubygems"
require "sinatra"
require "haml"
require "data_mapper"
require "pony"
get '/' do #works fine
haml :index
end
get '/:user_id/dashboard' do #recognizes the content but ignores layout.haml
haml :dashboard
end
my layout.haml looks like this:
views/layout.haml
!!!
%html
%head
%title Testing haml and sinatra
%link(rel="stylesheet" href="css/style.css")
%body
#wrapper
#header
%h1 HAML Test Template
%h2 Made with Sinatra and HAML!
#navigation
%h1 Navigation
#sidebar
%h1 Sidebar
#content
=yield
#footer
%p
This is the footer.
Any help would be much appreciated. Thanks.
I don't know if it matters but I'm using shotgun for development
I fixed this by using the following in layout.haml:
layout.haml
Instead of:
%link(rel="stylesheet" href="css/style.css")
Replaced (fixed version):
%link(rel="stylesheet" href="/css/style.css")
Works fine! Hopefully this helps someone.
If it helps, when I view source, it appears that it's trying to access my style.css in the wrong place based on the url parameter ":user_id" like so:
http://127.0.0.1:4567/test/myapp/css/style.css
So I need to get it to grab the style sheet form the same place it would if I was hitting 127.0.0.1/about which would look like this in the html source:
http://127.0.0.1:4567/css/style.css
In the actual code both stylesheet links are identical, but since I'm in a subdirectory it cannot find the stylesheet style.css
http://127.0.0.1:4567/css/style.css *(exists in public/css/style.css)*
-vs-
http://127.0.0.1:4567/test/myapp/css/style.css *(doesn't exist)*
I am still seeing an issue now with url parameters using a variable in the url path with sinatra and Haml.
When using these I am seeing the css becoming embedded into the post processed html instead of creating a link to the style.css file. The processed html is as follows (even the doctype is messed up and title isn't included):
I see this now with url parameters in the path (e.g. localhost:4567/user/add):
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
body { text-align:center;font-family:helvetica,arial;font-size:22px;
color:#888;margin:20px}
#c {margin:0 auto;width:500px;text-align:left}
</style>
</head>
Instead of this (e.g. localhost:4567/about):
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>Test app</title>
<link href='/css/style.css' rel='stylesheet' />
</head>
What am I missing here??

Google code prettify thinks css #id's are line comment. What am I doing wrong?

Example CSS
#wrap{margin:20px}
Code prettify wraps the whole line in .com
<span class="com">#wrap{margin:20px}</span>
Somebody has a similar issue here.
Where someone answers "Are you loading lang-css.js?".
Here's what I'm loading in the footer.
<script src="/js/google-code-prettify/lang-css.js"></script>
<script src="/js/google-code-prettify/prettify.js"></script>
I can see both of them with web inspector. I tried changing the order and loading them from the header. I'm using the latest version.
All help is greatly appreciated :)
Thanks!
The order you link to the javascript files matters. You need to call the base code (prettify.js) first followed by the css specific code (lang-css.js). You can place the script tags either in the head section or at the end of the document... both work but placing at the end of the document will speed up the page load.
<script src="/js/google-code-prettify/prettify.js"></script>
<script src="/js/google-code-prettify/lang-css.js"></script>
You will also need to ensure that you are linking the stylesheet in the head of your document.
<link rel="stylesheet" type="text/css" href="/css/prettify.css">
You also need to add the correct classes your pre tag(s). The syntax-highlighting functions contained in lang-css.js will not be called without adding the class "lang-css" to the <pre> tag.
<pre class="prettyprint lang-css linenums">
Finally, make sure you call the "prettyPrint()" function on page load.
<body onload="prettyPrint()">

What are the differences between using an iframe and ajax to include the contents of an external page?

I have been reading up on this, and it seems that if you use ajax you can only bring in content that resides on the same domain whereas with an iframe you can bring in content from any domain. Is that the case? What other differences are there?
Bear in mind they're two completely separate technologies.
A (i)frame really loads a complete HTML page in area into the browser. Whether the page is on the same or another domain, for pure viewing, doesn't matter.
Ajax only describes a system to facilitate JavaScript to talk with (and with current security restriction across browser, only with) the server from which you document within which you generated the JavaScript call from.
The (i)frame technology loads and renders a complete HTML page from any URL given. Certain security restrictions accessing other documents from other domains with JavaScript still apply.
With Ajax, it's only meant to use purely JavaScript to talk to the originating server (send some data) and usually get some data back. In JavaScript. What this data is and what you do with it, is up to you. Whether you insert it into the DOM (Document Object Model), exchange parts or load a new page is up to you.
To a certain degree you have all freedom you want. You can have an (i)frame on a page, still make a Ajax call and decide to load another URL into the (i)frame. Or use the Ajax return value to generate new HTML dynamically inside the (i)frame. Or outside, in another document.
The security restrictions applying in this case is called "same origin policy".
Quite simply, an iframe is like a regular frame, but it doesn't split the browser window up into sections, it sits right inside a page and is affected by the scrollbar.
Ajax, on the other hand, uses javascript to do partial loads of a page, allowing small amounts of data to be loaded from the server without needing to do a complete postback. For example, Youtube uses Ajax when you post comments, vote, queue videos to play, etc. They do this so that your video isn't interrupted and restarted by a complete page postback.
Besides these differences mentioned by others, there are others as well.
iframe loads an entire html/php page, whether it is from the own server or other external server. Usually, it has a fresh <html>, <head> and <body> tag as well. Ajax only loads part of the html/php page.
Besides, Ajax pulls the CSS (and maybe, even javascript codes) from the parent file, but in case of Iframe, it cannot pull the same.
E.g this is the master file coding.
<!doctype html>
<html>
<head>
<style>
.gappu {background-color:black;color:red;}
</style>
<meta charset="utf-8">
<script src="../AllJqueries/jquery-1.11.3.min.js"></script> <!-- Use your own jQuery file -->
<script>
<!--
$(document).ready(function(){
$.ajax({url:"slave1.php?bare=true", success:function(data){
$(".myDomain").html(data);
}});
}); /* End of Main Jquery */
//-->
</script>
<title>Ajax vs Iframe</title>
</head>
<body>
<div class="myDomain"></div>
<div>Iframe below</div>
<iframe width="100%" height="500px" src="slave1.php"></iframe>
</body>
</html>
Now, we also have another file, named as slave1.php
<?php
if(isset($_GET['bare'])) $bare = $_GET['bare'];
else $bare = false;
if(!$bare):
?>
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<style>
.gappu {background-color:blue;color:yellow;}
</style>
<!-- You can remove the above style later, and see the difference. The parent style will not apply for iframe -->
<title>Inside the Iframe</title>
</head>
<body>
<?php endif; ?>
<div class="gappu">Hi, welcome to this demo</div>
<?php if(!$bare): ?>
</body>
</html>
<?php endif;
In case of Ajax call, the line Hi, welcome to this demo will be in black background and red color, since it is borrowing the css from the parent. But in iframe, it will be in blue background and white color, which is defined in slave1.php. You can remove the style from slave1.php, and you will find plain text printed in iframe format.
Hope this helps. Cheers.
Vijay Srinivas

Resources