Rails streaming de videos

Ayant voulu mettre une vidéo en utilisant le streaming de rails je me suis heurté à un problème sur Internet Explorer 11

def recuperer_fichier
  @fichiers = Fichier.find(params[:id])
  Dir.glob("mon_chemin_vers_fichier/fichiers/*").each do |nom_fichier|
    send_file nom_fichier, disposition: "inline"
  end
end

Ci-dessus la méthode employé pour récupérer les vidéos (format mp4 et webm) qui marche sous firefox et chrome.

cependant sur Internet explorer 11 et safari une erreur survient.

Concernant Internet explorer, si au chargement de la page dans l’onglet reseau la vidéo possède le mime type suivant Application/octet-stream c’est qu’il faut passer un attribut type dans le send file.

  send_file nom_fichier, type: mime_type_du_fichier ,disposition: "inline"

Concernant Safari je n’ai trouvé aucune solution pour le moment.

Délai de répétition d’une vidéo

Si un jour l’envie vous prend de vouloir lancer une vidéo en lecture automatique et que vous voulez que celle-ci ce relance automatiquement après un délai de quelques secondes, voici comment faire :

il suffit d’écrire la balise vidéo habituelle avec les options que vous souhaitez :

<video width="561" height="374" controls="controls" autoplay="true" id="video" >
  <source src="video.mp4" type="video/mp4" />
  <source src="video.webm" type="video/webm" />
</video>

puis d’y inclure le JS suivant :

<code>
<script>
  $(function() {
    var video = $("#video").get(0);
    video.addEventListener("ended", function() {
      setTimeout(function(){
          video.play();
      }, 5000);
    });
  });
</script>
</code>

Petite explication du js :

On récupère avec l’id notre balise vidéo via un get(0).

Puis on écoute l’événement ended du gestionnaire d’événement, dans lequel on aura au préalable configuré un setTimeout avant de relancer la vidéo avec la fonction .play()

Dans notre cas la vidéo se relance 5 secondes après s’être arrêter.

Astuce : si l’attribut loop est présent dans la balise vidéo l’événement ended n’arrive jamais.

 

Configurer le temps d’expiration d’une session rails

Pour configurer manuellement le temps d’expiration des sessions il faut aller dans le fichier config/initializers/session_store.rb et modifier la ligne suivante :

Reference::Application.config.session_store :cookie_store, key: '_projet_session', expire_after: 1.minute

Modifier la valeur 1.minute par la valeur que vous souhaitez.

source : stack overflow

 

Etendre le support HTML5/CSS3 à IE

N’importe quel navigateur moderne de nos jour est capable de reconnaitre et d’utiliser en grande partie les propriétés CSS3 et les balise HTML 5 tous sauf notre irréductible Internet Explorer.

Nous allons voir dans cet article comment avoir le meilleur support sur les anciens navigateurs et plus particulièrement les anciennes versions d’IE.

Commençons par les balises HTML5

HTML5shiv

Html5shiv est un script JS qui permet d’étendre les balises HTML5 aux versions inférieures d’IE10.

Il suffit pour cela d’ajouter dans le head de la page le script disponible ici

<!-- [if lt IE 9]>
    <script src="chemin/vers/html5shiv.js"></script>
<![endif]-->

Une fois cela fait il ne reste plus qu’à utiliser les nouvelles balises. Attention il est nécessaire d’utiliser un serveur. Sans une boucle localhost le script ne fonctionnera pas.

Passons au CSS.

CSS3 Pie

CSS3 Pie est une bibliothèque qui permet d’émuler des propriétés css de IE 6 – à IE 9, elle est disponible sur le site de css3pie.

Les propriétés qui peuvent être émuler sont les suivantes :

Pour ce qui est de l’utilisation, il suffit d’inclure les fichiers dans votre projet. Ensuite d’écrire votre CSS comme ceci :

.test{
      background-color: FireBrick;
      margin-bottom: 1em;
      border: 1px solid black;
      -webkit-border-radius: 10px;
      -moz-border-radius: 10px;
      border-radius: 10px;
      behavior: url(PIE.htc);
    }

La propriété behavior: url(chemin/vers/le/fichier/PIE.htc) est obligatoire.

Elle ne marche qu’avec internet explorer, elle permet d’associer un script javascript à un objet HTML.

Encore une fois cela ne marche que si l’on passe par une boucle localhost.

Petite précision importante sur cette bibliothèque, elle ne reconnait que les propriétés de type « short-hands » par exemple : border radius: 10px ou border-radius 10px 10px 10px 10px.

Mais ne reconnais pas la propriété suivante border-radius-top-left: 10px;

Selectivizr

Selectivizr est un petit script qui permet d’émuler les pseudos classes pour IE 6 à IE 8 disponible sur le site de seletivizr.

Il suffit d’inclure le script dans le head de la page :

<!--[if (gte IE 6)&amp;(lte IE 8)]>
  <script type="text/javascript" src="selectivizr.js"></script>
<![endif]-->

et de posséder une bibliothèque parmi les suivantes :

  • Jquery
  • Dojo
  • Prototype
  • yahoo
  • DomAssistant
  • mootools
  • nvwmatcher

Par ailleurs pour une émulation de toutes les pseudos classes il est nécessaire d’utiliser mootools ou nvwmatcher. Les autres ne permettent qu’une émulation partielle.

Flexbox

Enfin pour rendre compatible les flexbox avec IE10 il faut doubler les propriétés css avec le préfixe -ms- à chaque fois que vos utiliser une propriété flexbox par exemple de cette façon :

display: -ms-flexbox;           /* TWEENER - IE 10 */
display: flex;

Cela permet une compatibilité avec IE10.

Cependant si vous viser une compatibilité inférieur à IE10 il est possible d’utiliser le Polyfill flexibility disponible ici

Ce polyfill n’est cependant pas complet et ne supporte pas toutes les propriétés flexbox. Cela permet un mode dégradé plus sympathique mais ne vous attendez pas à un support complet.

Mes tests ce sont portés principalement sur une version IE 8 je ne sais pas si sur la version d’IE 9 le support est meilleur.

Pour l’utilisation, il suffit encore une fois d’inclure le script dans notre projet :

<script src="flexibility.js"></script>

Ensuite il faut mettre devant chaque display: flex la propriété suivante :

-js-display: flex;

Pour savoir si le navigateur utilisé supporte ou pas les flexbox il est possible d’utiliser modernizr. (voir l’article)

if (Modernizr.flexbox &amp;&amp; Modernizr.flexwrap) {
    // Modern Flexbox with `flex-wrap` is supported
} else {
    flexibility(document.documentElement);
}

Knockout JS

Knockout.js est un framework qui permet de de simplifier les interfaces utilisateurs et de les rendre dynamique de manière simple.

Cette bibliothèque permet d’implémenter le pattern MVVM ( modèle vue vue modèle). Cela permet de créer une liaison dynamique entre un modèle de données et une vue.

Concernant la compatibilité la bibliothèque est supporté par : IE 6+, Firefox 3.5+, Chrome, Opera, Safari (desktop/mobile).

 

Exemple simple :

//déclaration d'une vue-modèle qui contient les données de liaison
function AppViewModel() {
    this.prenom = "Bert";
    this.nom = "Bertington";
}
// active la liaison de données
ko.applyBindings(new AppViewModel());

 

Prénom:

Nom:

 

Donc si le Js est modifié la vue est modifié. Si l’on veux une liaison bi directionnelle pour respecter le pattern MVVM il suffit de réécrire le js de cette façon

function AppViewModel() {
    this.prenom = ko.observable("Bert");
    this.nom = ko.observable("Bertington");
}
 
// Activates knockout.js
ko.applyBindings(new AppViewModel());

Dorénavant la modification d’une vue entraine la modification du modèle est inversement.

Ceci est un exemple simple il est possible de retrouver sur le site officiel des tutoriels en live qui sont plus concret et intéressant.

Knockout js me semble une petite bibliothèque puissante permettant de faire pas mal de chose simplement. Il semble y avoir pas mal de documentation, aucune dépendance et étant faite en JS pur elle est compatible avec beaucoup de navigateur.

 

source : knockout js

Thread : connexion base de donnée

Un thread est une unité d’exécution. Cette unité fonctionne de façon autonome et parallèlement à d’autres threads. Le principal avantage des threads est de pouvoir répartir différents traitements d’un même programme en plusieurs unités distinctes pour permettre leurs exécutions « simultanées ».

Pour créer un thread rien de plus simple il suffit de faire :

thr = Thread.new { #code lancé en parallèle }

Il existe une méthode status qui permet de retourner le statut d’un thread qui peut être utilisé de la manière suivante :

thr.status

Cette méthode peut retourner les valeurs suivante :

sleep => le thread est en attente

run => le thread est en cour d’exécution

aborting => le thread est en cours d’annulation

false => le thread est terminé normalement

nil => le thread est terminé avec une exception

Il existe deux autres méthodes :

thr.list
thr.kill

List permet de lister les threads qui sont arrêter ou qui sont en cour d’exécution.

Kill quant à lui permet de stopper un thread.

Dans l’idée les threads sont bien pratiques, cependant lorsque l’on commence a faire des thread.new l’erreur suivante « could not obtain a database connection within 5.000 seconds » est souvent levée.

Dans une application rails on a ce qu’on appel un pool de connexion définit à 5 par défaut et un timeout définit à 5 secondes. Ceci étant configurable dans le database.yml.

D’où la première solution logique qui à été d’augmenter ce pool de connexion. Cependant je ne sais pas quelles sont toutes les conséquences de cette action et jusqu’à quelle point peut-on augmenter ce pool de connexion ?

Malheureusement cela ne suffit pas a vaincre l’erreur qui met juste plus de temps a survenir.

Il apparaît que lorsque Rail utilise des threads ces derniers sont gérés correctement. Mais si on créer nos propres threads il faut les gérer nous même.

En effet, lorsque un thread se lance celui-ci va utiliser une connexion selon le pool de connexion disponible. Mais lorsqu’il meurt la connexion devient « orpheline » appelé aussi « fuite de connexion » et devient inutilisable. Donc si toutes les connexions deviennent orphelines il n’y à plus de connexion disponible donc l’erreur « could not obtain a database connection within 5.000 seconds » est levée.

Pour palier ce problème il existe une méthode « clear_stale_cached_connections! » qui permet de nettoyer les connexions orphelines. Cette méthode est valable en Rails 3.x.

Pour ce qui est de Rails 4 cette méthode à été réécrite et ne fait plus du tout la même chose.

Donc une solution qui semble valable en Rails 4 est la suivante :

Il faut ajouter dans la création du thread les lignes suivantes :

Thread.new {
  begin
    # Do whatever
  ensure
    ActiveRecord::Base.connection_pool.release_connection
  end
}

La ligne ActiveRecord::Base.connection_pool.release_connection permet donc de cleaner les connexions.

Malgré tout une autre erreur peut être levée « ActiveRecord::StatementInvalid (Mysql2::Error: This connection is in use by: #<Thread:0x007f99b6aa59e0 dead> » cette erreur n’arrête pas l’exécution du processus.

Il faut donc ajouter le code suivant dans le ensure si l’on veux gérer cette erreur :

Thread.new {
          begin
            # Do whatever
          ensure
            begin
              if (ActiveRecord::Base.connection && ActiveRecord::Base.connection.active?)
                ActiveRecord::Base.connection_pool.release_connection
              end
            rescue
            end
          end
        }

Avec ceci je n’ai pas réussi a reproduire les erreurs obtenu.

 

source : bibwild.wordpress.com

stackoverflow

le paradigme des Promesses

Promesses.

Les promises (pour promesses) sont des objets en JS, représentant une valeur qui pourrait être retournée par l’exécution d’une opération unique de façon asynchrone.

Pour prendre un exemple simple  « imaginons que votre maman vous promet de vous acheter un nouveau téléphone la semaine prochaine ».

Vous ne savez pas si vous allez avoir ce téléphone jusqu’à ce que le jour J arrive. Votre maman peut vraiment acheter le téléphone ou bien elle peut refuser de l’acheter car vous n’avez pas été gentil.

Cela nous donne trois états :

  • Pending : la promesse est en attente.
  • Resolved : la promesse est tenue
  • Rejected: la promesse est rompue

Une fois tenue ou rompue la promesse ne peut plus changer d’état.

exemple :

var isMomHappy = false;
 
// Promesse
var willIGetNewPhone = new Promise(
    function (resolve, reject) {
        if (isMomHappy) {
            var phone = {
                brand: 'Samsung',
                color: 'black'
            };
            resolve(phone); // promesse tenue
        } else {
            var reason = new Error('mom is not happy');
            reject(reason); // promesse rompue
        }
 
    }
);

Dans cet exemple simple, nous avons un booléen isMomHappy, qui détermine si maman est contente ou pas.

Nous avons ensuite notre promesse willIGetNewPhone qui peut être tenue ou non selon l’humeur de maman.

Si la promesse est tenue, on appel resolve(ma_valeur_succes), donc on récupère notre téléphone =). À contrario si la promesse est rompue on appelle reject(ma_valeur_erreur) maman n’est pas contente est donc pas de téléphone =(

// appel de la promesse
var askMom = function () {
    willIGetNewPhone
        .then(function (fulfilled) {
            // yay, you got a new phone
            console.log(fulfilled);
        })
        .catch(function (error) {
            // ops, mom don't buy it
            console.log(error.message);
        });
}
 
askMom();

Ici on appel notre promesse on demande à maman si je vais avoir un nouveau téléphone. Pour contrôler notre action il y a deux mots clefs .then et .error.

Dans notre cas le .then est suivi de function(fullfilled){ … } la valeur de fulfilled est la valeur en cas de succès => le téléphone.

dans le catch est suivi de function(error){ … } la valeur d’error est la valeur en cas d’échec => le mécontentement de maman.

Chaînage de promesse

Après que maman m’est promis un nouveau téléphone j’ai été voir voir mon copain pour lui promettre que je lui montrerais une fois que j’aurais ce téléphone.

var showOff = function (phone) {
    return new Promise(
        function (resolve, reject) {
            var message = 'Hey friend, I have a new ' +
                phone.color + ' ' + phone.brand + ' phone';
 
            resolve(message);
        }
    );
};

Dans cet exemple on peut voir que le reject est optionnel pour une promesse. Et que la promesse showOff débute après la promesse willIGetNewPhone.

Asynchronisme

Les promesses sont asynchrones. qu’est-ce que cela veux dire ? cela veux dire que la lecture du programme peut continuer pendant le traitement d’une promesse.

// appel de la promesse
var askMom = function () {
    console.log('before asking Mom'); // log avant
    willIGetNewPhone
        .then(showOff)
        .then(function (fulfilled) {
            console.log(fulfilled);
        })
        .catch(function (error) {
            console.log(error.message);
        });
    console.log('after asking mom'); // log après
};

La séquence qui est attendu est la suivante :

1. before asking Mom
2. Hey friend, I have a new black Samsung phone.
3. after asking mom

Mais la séquence obtenu est la suivante :

1. before asking Mom
2. after asking mom
3. Hey friend, I have a new black Samsung phone.

 

L’exécution du code continu sans blocage, ni sans attendre de résultat.

 

Source :

Les promesses pour les nuls

Web fundamental

MDN

 

Ridiculously Responsive Social Sharing Buttons

Ridiculously Responsive Social Sharing Buttons est un plugin javascript permettant d’ajouter des liens de partages vers différents réseaux sociaux.

Parmi tout les plugins existant celle-ci comporte plusieurs avantage :

  • il est responsive
  • il est gratuite
  • il possède de nombreux réseaux sociaux de base
  • il est facile d’utilisation

Utilisation

Pour ce qui est de l’utilisation il suffit d’ajouter le fichier css « rrssb.css » dans notre projet et de copier la balise <link> suivante dans notre header :

<link rel="stylesheet" href="css/rrssb.css" />

Ensuite il suffit de choisir les réseaux que l’on souhaite ajouter, en copiant les li correspondant présent dans le fichier index.html.

Et enfin il est nécessaire de copier les lignes de JS suivante est de copier le fichier rrssb.min.js dans notre projet. (Si Jquery est déja présent dans notre projet la première ligne est optionnel)

&lt;script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"&gt;&lt;/script&gt;
&lt;script&gt;window.jQuery || document.write('&lt;script src="js/vendor/jquery.1.10.2.min.js"&gt;&lt;\/script&gt;')&lt;/script&gt;
&lt;script src="js/rrssb.min.js"&gt;&lt;/script&gt;

Voilà maintenant que nos boutons sont disponible il suffit de changer les liens dans chaque li par le liens que vous voulez partager.

Si jamais vous n’aimer pas faire d’effort inutilement voici un morceau de JS qui permet de remplacer  les liens automatiquement.

&lt;script type="text/javascript"&gt;
 
jQuery(document).ready(function ($) {
 
  $('.rrssb-buttons').rrssb({
    // required:
    title: 'This is the email subject and/or tweet text',
    url: 'http://rrssb.ml/',
 
    // optional:
    description: 'Longer description used with some providers',
    emailBody: 'Usually email body is just the description + url, but you can customize it if you want'
  });
});
&lt;/script&gt;

source :

git hub

demo

Sous tableau avec dataTable

Lorsque l’on à un dataTable sur une vue et que l’on veux cliquer sur une ligne du tableau pour déplier cette ligne et y voir de nouvelles informations, cela peut devenir compliqué et l’on peux vite faire du code pas très propre.

DataTables propose une api, rowChild pour pouvoir créer des sous tableaux dans un table de manière moins sale.

function format ( d ) {
    // `d` is the original data object for the row
    return '&lt;table cellpadding="5" cellspacing="0" border="0" style="padding-left:50px;"&gt;'+
        '&lt;tr&gt;'+
            '&lt;td&gt;Entretiens:&lt;/td&gt;'+
            '&lt;td&gt;'+d[1]+'&lt;/td&gt;'+
        '&lt;/tr&gt;'
    '&lt;/table&gt;';
}

La fonction format permet de passer l’objet ( une ligne du tableau ) et ainsi de recréer un tableau en allant rechercher les informations que l’on veux afficher dans un tableau javascript.

$(document).ready(function() {
  var table = $('.table').DataTable( {
      "iDisplayLength": 100,
      'oLanguage': {
          'oPaginate': {
              'sPrevious': 'Page précédente',
              'sNext': 'Page suivante',
              'sLast': 'Dernière page',
              'sFirst': 'Première page',
          },
         'sInfoEmpty': 'Aucune infos à afficher',
         'sInfo': '_TOTAL_ iinfos à afficher (_START_ à _END_)',
         'sEmptyTable': 'Aucune infos à afficher',
         'sInfoFiltered': ' - filtrées de _MAX_ enregistrements',
         'sLengthMenu': 'Afficher _MENU_ infos',
         'sSearch': 'Recherche :',
         'sZeroRecords': 'Aucun résultat pour cette recherche'
      },
        responsive: {
            details: {
                type: 'column',
                target: 'tr'
            }
        },
        columnDefs: [ {
            className: 'control',
            orderable: false,
            targets:   0
        }
 
 
         ],
        order: [ 1, 'asc' ]
  });

Dans le document.ready il faut ajouter une classe pour cibler une colonne, ici « control » qui va permettre de gérer l’affichage au clic

  $('.table tbody').on('click', 'td.control', function () {
      var tr = $(this).closest('tr');
      var row = table.row( tr );
 
      if ( row.child.isShown() ) {
          // This row is already open - close it
          row.child.hide();
          tr.removeClass('shown');
      }
      else {
          // Open this row
          row.child( format(row.data()) ).show();
          tr.addClass('shown');
      }
  });

Il faut aussi bien penser à ajouter bootstrap.js et jquery pour que cela fonctionne.

source : DatatTable

Support des fonctionnalités

@supports

Appelé aussi règle conditionnelle, le @supports permet de détecter si une propriété css est compatible avec le navigateur utilisé par l’internaute, et ainsi prévoir une alternative si besoin.

Cette propriété et supporté par à peu près tout les navigateurs modernes sauf l’irréductible IE. Can i use

Tout comme les médias queries, @supports peut intégrer plusieurs règles au sein d’un bloc d’accolade. Et les conditions doivent êtres individuelles et entourées par des parenthèses.

@supports (hyphens: auto){
    p{
       hyphens: auto
     }
}

Si le navigateur supporte la propriété hyphens il va l’appliquer sinon il va s’adapter avec les conditions par défaut.

Il est possible d’ajouter des conditions and et or comme avec les medias queries, ainsi que tester la non reconnaissance d’une propriété avec l’opérateur not.

Toutefois certaines règles que l’on testes sont mieux supportées que le @supports lui même, notamment sur IE. Donc le résultat peut être trompeur.

@supports et javascript

Il est possible d’utiliser @supports avec le javascript. Il y a deux syntaxes possible :

if ( CSS.supports('property', 'value') )  { }
 
if ( CSS.supports( '(property: value) and (property: value') ) { }

Conclusion

C’est une propriété assez intéressante dans la théorie, mais malheureusement du fait de sont manque de compatibilité sous IE, la pratique n’est pas forcément utile.

En effet celle ci ne sera utile que si la propriété testée n’est pas compatible avec plusieurs navigateurs, tels que hyphens, et que celle-ci ne demande pas non plus un travail trop important en solution alternative.

Source: alsacreation, MDN