1. Override Devise Registration Controller

    Override Devise

    Introduction

    I want to create a user directly linked to a company. In this case you must change the basic behavior of Devise . Of course you can override by copying the controller in app/controllers and indicating Devise to use your new route, but I wanted to find an nicely solution, I got a ticket that has put me on the good way.

    Models

    Here is a simple representation of my models

    Devise User

    class User
        include Mongoid::Document
        # Include default devise modules. Others available are:
        # :confirmable, :lockable, :timeoutable and :omniauthable
        devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable
    
        ...
    
        belongs_to :company
        validates :company, presence: true
        validates_associated :company
        accepts_nested_attributes_for :company
    end
    

    Company model

    class Company
        include Mongoid::Document
        field :name, type: String
    
        has_many :users
            validates :name, presence: true
            validates_uniqueness_of :name, case_sensitive: true, allow_blank: false
    end
    

    I’ve changed new devise registration view

    .container
        = simple_form_for resource, as: resource_name, url: registration_path(resource_name) do |f|
            = f.simple_fields_for :company, resource.company do |company_fields|
                = company_fields.input :name, autofocus: true, as: :string
            = f.input :email, as: :string
            = f.input :password, as: :password
            = f.input :password_confirmation, as: :password
            .form-group
                = f.button :submit
    

    Devise provide RegistrationController with this new action :

    class Devise::RegistrationsController < DeviseController
        prepend_before_filter :require_no_authentication, :only => [ :new, :create, :cancel ]
        prepend_before_filter :authenticate_scope!, :only => [:edit, :update, :destroy]
    
        # GET /resource/sign_up
        def new
            build_resource({})
            respond_with self.resource
        end
    
        ...
     end
    

    Changes attemps

    I rely on ActiveModel and nested attributes to build my object from the parameters, so I want to change

    build_resource ({})
    

    for

    build_resource({ comapny_attributes: {} })
    

    Show in the console my expectations :

    >> user = User.new({company_attributes:{}, email:'me@joelazemar.fr', password:'secret', password_confirmation:'secret'})
    >> user.company
    => #<Company id: nil, name: nil, created_at: nil, updated_at: nil>
    

    Ok great the company has been added to my User and validations can be correctly

    >> user.valid?
    => false
    >> user.errors.full_messages
    => ["Company is invalid"]
    >> user.company.errors.full_messages
    => ["Name can't be blank"]
    

    Ok now up to the magic of Ruby

    I want change Registration new action for pre build a new empty resource.company, this will allow me to leave SimpleForm and Rails do their job!

    adding my new wanted action of Registration controller called ‘custom_new’

    module DeviseRegistrationsControllerDecorator
        extend ActiveSupport::Concern
    
        def custom_new
            build_resource({ comapny_attributes: {} })
            respond_with self.resource
        end
    end
    
    Devise::RegistrationsController.send(:include, DeviseRegistrationsControllerDecorator)
    

    Alias and Redefinition

    Finally, I updated the module so that when it was included, an alias for the core new method, and an override of the core new method with the custom_new method:

    module DeviseRegistrationsControllerDecorator
        extend ActiveSupport::Concern
    
        included do
            alias :devise_new :new
            def new; custom_new; end
        end
    
        def custom_new
            ...
        end
    end
    
    Devise::RegistrationsController.send(:include, DeviseRegistrationsControllerDecorator)
    

    Development mode

    config/environments/development.rb

    Because classes are not cached in development, and library modules are not automatically reloaded, I added the following call to config/environments/development.rb to force a reload of the module to ensure that the devise controller would always be extended:

    config.to_prepare do
        Devise::RegistrationsController.send(:include, DeviseRegistrationsControllerDecorator)
    end
    

    Conclusion

    In this case, ActiveSupport::Concern was used to easily override the core devise method without requiring hacking at the source code. One disadvantage to this implementation is that if significant changes are made to the core method, those changes also need to be applied to the custom controller if necessary.

    Thank you to Steph Skardal and hoping that it may be used to the other.

    Source http://blog.endpoint.com/2012/06/devise-on-rails-prepopulating-form-data.html

     

  2. Ruby Thread with Rspec

    Ruby Thread with Rspec

    Introduction

    One may wish to start the execution of the code so as concurently manner in production or in development mode, but sometimes when you want to pass a test is to be hoped that this code is not executed in parallel but inline to retrieve the correct value in our test . I was personally exposed to it and that’s how I do. This is perhaps not the best solution but in my case it’s perfectly fulfills its role.

    Sample

    Consider a perfectly stupid work but the result is different if the execution is inline or concurently

    sleeper = (1..3).to_a.reverse
    ['foo', 'bar', 'zone'].each_with_index do |variable, index|
      sleep sleeper[index]
      result << variable
    end
    

    now you want threadify this job

    One way to do that is

    [].tap do |threads|
        sleeper = (1..3).to_a.reverse
        ['foo', 'bar', 'zone'].each_with_index do |variable, index|
            threads << Thread.new do
                sleep sleeper[index]
                result << variable
            end
        end
    end.each &:join
    

    The concern here is that the code will no longer execute inline

    Here is the path I took to keep the 2-way

    I wrote an Module

    module Threadify
    
      attr_accessor :jobs
    
      def jobs
        @jobs ||= []
      end
    
      def prepare async = true
        if async
          thread = asyncronous { yield }
          jobs << thread
        else
          proc = inline { yield }
          jobs << proc
        end
      end
    
      def launch async = true
        async ? jobs.each(&:join) : jobs.each(&:call)
      end
    
      private
    
      def asyncronous
        Thread.new { yield }
      end
    
      def inline
        Proc.new { yield }
      end
    
    end
    

    In my code I called jobs like that

    class Main
      include Threadify
    
      attr_accessor :result
    
      def initialize
        @result = []
      end
    
      def work async = true
        sleeper = (1..3).to_a.reverse
        ['foo', 'bar', 'zone'].each_with_index do |variable, index|
          prepare(async) do
            sleep sleeper[index]
            result << variable
          end
        end
      end
    
      def start async = true
        work async
        launch async
      end
    end
    

    Now I can call the code of 2 ways

    describe 'Sample' do
      subject { Main.new }
      context 'inline' do
        let(:async) { false }
        before { subject.start async }
        it 'should keep order' do
          subject.result.should eql ['foo', 'bar', 'zone']
        end
      end
      context 'async' do
        let(:async) { true }
        before { subject.start async }
        it 'should reverse order' do
          subject.result.should eql ['zone', 'bar', 'foo']
        end
      end
    end
    

    The code of this sample is here

     

  3. Call Method through collection

    Introduction

    I had the idea to call an object method through a collection, this is how i did..

    Make a simple Object class person with money method

    class Person
      attr_accessor :money
    end
    

    You can pass by a Proc like that

    You grab new instance of John et Bob

      john, bob = Person.new, Person.new
    

    Defined Proc set_money

      set_money = Proc.new do |person, money|
        person.__send__ :money=, money
      end
    

    And you can iterate on your object collection and call your proc, like that

      [john, bob].map do |person|
        set_money.call person, rand(100)
      end
    
      puts "John have #{john.money}$"
      puts "Bob have #{bob.money}$"
    

    You obtain that

      => John have 44$
      => Bob have 74$
    

    Ok great its cool, but i want go more deeper…

    You can Monkey Patch Array with method missing like that

    class Array
    
      def method_missing method_name, *args
        self.each do |element|
          raise "undefined method `#{method_name}` for #{element}" unless element.respond_to?(method_name)
          element.public_send(method_name, *args) if element
        end
      end
     end
    

    You start again

    begin
      john, bob = Person.new, Person.new
      [john, bob].__send__ :money=, 100
    
      puts "John have #{john.money}$"
      puts "Bob have #{bob.money}$"
    end
    

    You obtain that

    => John have 100$
    => Bob have 100$
    

    Yeah! It work! Seems look better, no? Ok ok.. NO! It’s not a good idea to Monkey Patch Array, but you can make that on different way, look that:

    I’m defined a wrapper class, for encapsulate my modified Array Class

    class Wrapper < Array
    
      def self.wrap object
        if object.kind_of? Array
          array = new
          object.each do |element|
            raise 'none recursive array are supported' if element.kind_of? Array
            array << element
          end
          array
        else
          object
        end
      end
    
      def method_missing method_name, *args
        self.each do |element|
          element.__send__(method_name, *args) if element && element.respond_to?(method_name)
        end
      end
    end
    

    Start again

    begin
      john, bob = Person.new, Person.new
      Wrapper.wrap([john, bob]).__send__ :money=, 100
    
      puts "John have #{john.money}$"
      puts "Bob have #{bob.money}$"
    end
    

    You obtain that

    => John have 100$
    => Bob have 100$
    

    Ok it the really good way for that, you can serve to behavior of chosen class without altering for all of your application scope.

     

  4. Management variables scope for inline conditions by Ruby

    Management variables scope for inline conditions by Ruby

    Classic way

    class ActiveRelation
        def exists?; true; end
        def first; 'Roger Rabbit'; end
      end
    
      class PetStore
    
        def guinea_pig
          if (result = item).exists?
            result.first
          end
        end
    
        def item
          ActiveRelation.new
        end
      end
    

    No problem here

    puts “#1 PetStore.new.guinea_pig => #{PetStore.new.guinea_pig}”

    #1 PetStore.new.guinea_pig => Roger Rabbit
    

    Inline Way

    Normally the variable should have the same access, if the condition is written inline

      class PetStore
    
        def guinea_pig
          result.first if (result = item).exists?
        end
    
        def item
          ActiveRelation.new
        end
      end
    

    However, the variable is not available here? :/

      begin
        puts "#2 PetStore.new.guinea_pig => #{PetStore.new.guinea_pig}"
      rescue Exception => e
        puts "#2 #{e.message}"
      end
    

    Output :

      #2 undefined local variable or method `result' for #<PetStore:0x007fb962909660>
    

    What happened behind the scene ?

    In fact Ruby make a Proc for managed inline condition, therefore the variable is not accessible out the box !

      class PetStore
    
        def guinea_pig
          if Proc.new { (result = item).exists? }
            result.first
          end
        end
    
        def item
          ActiveRelation.new
        end
      end
    
      begin
        puts "#3 PetStore.new.guinea_pig => #{PetStore.new.guinea_pig}"
      rescue Exception => e
        puts "#3 #{e.message}"
      end
    

    Output :

    #3 undefined local variable or method `result' for #<PetStore:0x007fb962909660>
    
     

  5. Template Converters ERB => SLIM

    How convert your .erb to .slim :

    You must pass through HAML !

    Install HAML dependencies on your environment or your gemset

    gem install haml # https://github.com/haml/haml
    gem install hpricot
    gem install ruby_parser
    

    Switch to HAML templating

    find . -name '*erb' | \
    xargs ruby -e 'ARGV.each { |i| puts "html2haml -r #{i} #{i.sub(/erb$/,"haml")}"}' | \
    bash
    

    Install SLIM tool dependency

    gem install haml2slim # https://github.com/fredwu/haml2slim
    

    Switch to SLIM templating

    find . -name '*haml' | \
    xargs ruby -e 'ARGV.each { |i| puts "haml2slim #{i} #{i.sub(/haml$/,"slim")}"}' | \
    bash
    

    Clean ERB and HAML templates

    find . -name '*erb' -exec rm -f {} \;
    find . -name '*haml' -exec rm -f {} \;
    

    Remove dependencies

    gem uninstall haml
    gem uninstall hpricot
    gem uninstall ruby_parser
    gem uninstall haml2slim
    

    That all, have fun

     

  6. Application Rails 3.2.9 Without ActiveRecord

    Switch from ActiveRecord from MongoDB through Mongoid

    images

     

  7. Ruby autoload with namespaces

    Simple example of autoload with namespace

    into my file foo_module.rb

    
      puts "i'm loaded"
    
      module My
        module FooModule
          extend self
        
          # My::FooModule.print
          def print
            puts 'foo'
          end
    
        end
      end
    

    In Irb Console try this 2 ways :

    regular way

    
      irb
      >> require './foo_module'
      i'm loaded
      => true
      >> My::FooModule.print
      foo
      => nil
    

    autoload way :

    
      irb
      >> autoload :My, './foo_module'
      => nil
      >> My::FooModule.print
      i'm loaded
      foo
      => nil
    
     

  8. Ruby 1.9.3-p194 and Bundler

    If you update your version of Ruby to Ruby 1.9.3 patch 194 you might to see Rails don’t work anymore :(

    The problem is the naming of the file Wrapper Bundler.

    ~/.rvm/gems/ruby-1.9.2-p290@global/bin/bundler_wrapper
    ~/.rvm/gems/ruby-1.9.3-p194@global/bin/ruby_bundler_wrapper

    Env :

    bundler-1.1.3
    rvm 1.13.4
    Rails 3.2.3

     

  9. Passer sous Ruby 1.9.3-p0 avec RVM

    Mettez à jour la version de RVM => 1.9.2
    $ rvm get latest

    Mettez à jour la version de RubyGem => 1.8.11
    $ gem update --system

    Enfin installer Ruby 1.9.3
    $ rvm install 1.9.3-p0

    Ou avec rbenv :

    $ brew update
    $ brew install rbenv
    $ brew install ruby-build
    $ rbenv install 1.9.3-p0
    $ rbenv global 1.9.3-p0

     

  10. ImageMagick

    ImageMagick est extrêmement puissant mais n’est pas très simple a utiliser ou du moins les docs me sont étrangement ésotérique.

    Ayant dû manipuler des images je vous livre les commandes.

    Afin de générer un graphique avec un grand nombre d’entrée j’ai du segmenter les envoient à Google Chart Image qui m’a donc renvoyé un morceau de Graphique à chaque appel, afin de livrer un graphique utilisable sur une seule image j’ai dû passer par plusieurs manipulations

    L’image brut :

    Image Brut

    Premièrement supprimer les espaces

    convert image_0.png -crop 300x1000+4+0 image_0_crop.png

    Image cropée :

    Image Cropee

    La taille maximum de l’image renvoyé par Google Chart Image est de 300 000 pixels, afin d’optimiser le nombre de points tracé on ne va pas demander à Google Chart Image de nous ajouter les axes, mais nous allons les faire nous même :

    Pour l’axe des abscisses on va ajouter des images d’axe vierge

    puis on va créer l’image horodatée correspondante (Toutes les 10 minutes)

    command = "convert -size 300x60 canvas:none -pointsize 20 -fill black -draw \"text 123,45 '"
    command.concat(@date.advance(:minutes => +(5+(index*10))).strftime(ChartLine::TIME_FORMAT))
    command.concat("'\" hour.png")
    

    Puis on va composer l’image :

    composite hour.png axis_of_x.png axe.png
    

    On va coller le graphique dans une frame afin d’ajouter la place pour recevoir l’échelle des abscisses :

    composite -gravity North image_0_crop.png frame.png image_0_frame.png
    

    Maintenant on peut coller le morceau d’axe d’abscisse au morceau de graphique que nous avons

    composite -gravity South axe.png frame.png image_0_axis.png
    

    Ceci étant légèrement différent pour la première image car elle doit recevoir en + l’axe des ordonnées :

    Pour cela on choisit une frame un peu plus large

    composite -gravity East image_0_axis.png first_frame.png image_0_first.png
    

    On colle l’axe des ordonnées

    composite -gravity West axis_of_y.png image_0_first.png image_0_axis.png
    

    Pour la suite on peut itérer sur toutes les images composées et on les collent :

    convert image1.png image2.png image3.png +append -quality 75 imagefinale.png
    

     

  11. Rvm Bundler Rails 3.1 Thin Ubuntu

    Fichier /etc/init.d sous Ubuntu pour démarrer son app dans son environnement propre

      #! /bin/sh
      ### BEGIN INIT INFO
      # Provides:       <app_name>
      # Required-Start: $syslog
      # Required-Stop:  $syslog
      # Should-Start:       $local_fs
      # Should-Stop:        $local_fs
      # Default-Start:  2 3 4 5
      # Default-Stop:       0 1 6
      # Short-Description:  <app_name> - Site Web
      # Description:        <app_name> - Site Web
      ### END INIT INFO
    
    
      PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
      DAEMON=$HOME/.rvm/gems/ruby-1.9.2-p180@<app_name>/bin/thin
      DESC="<app_name>"
      NAME=<app_name>_env
      PROJECT_PATH=/var/www/$NAME # env
    
      check_thin() {
        for i in `ps aux|grep thin|grep '<app_name>.thin'|grep 'sock'|awk '{print $2}'`; 
        do 
            echo "Thin on $i"; 
            sleep 1; 
        done
      }
    
      test -x $DAEMON || exit 0
    
      set -e
    
      case "$1" in
        start)
            echo "Starting $DESC ..."
            rvm_path=$HOME/.rvm/ $HOME/.rvm/bin/rvm-shell '1.9.2-p180@<app_name>' -c \
            'cd /var/www/<app_name>_env/current/ && bundle exec thin -C \
            /etc/thin/<app_name>_env.yml start'
            echo "$DESC is started !"
        ;;
        stop)
            echo "Stopping $DESC ..."
            rvm_path=$HOME/.rvm/ $HOME/.rvm/bin/rvm-shell '1.9.2-p180@<app_name>' -c \
            'cd /var/www/<app_name>_env/current/ && bundle exec thin -C \
            /etc/thin/<app_name>_env.yml stop'
            echo "$DESC is stopped !"
        ;;
        restart|force-reload)
            echo "Restarting $DESC ..."
            rvm_path=$HOME/.rvm/ $HOME/.rvm/bin/rvm-shell '1.9.2-p180@<app_name>' -c \
            'cd /var/www/<app_name>_env/current/ && bundle exec thin -C \
            /etc/thin/<app_name>_env.yml restart'
            echo "$DESC is started !"
        ;;
        status)
            echo "Status"
            check_thin
        ;;
        *)
            N=/etc/init.d/<app_name>
            echo "Usage: $N {start|stop|restart|force-reload|status}" >&2
            exit 1
        ;;
      esac
    
      exit 0
    
     

  12. Ajouter une api key d’authentification dans toutes les requêtes ActiveResource pour Devise

    J’ai chercher du coté de Rack en middleware pour ajouter les paramètres d’authentification attendu par devise lorsqu’on active l’option :token_authenticatable mais malheureusement je n’ai pas réussi à les ajouter…

    Cependant j’ai trouvé une solution en surchargeant les méthodes d’ActiveResource

    Ajouter la librairie suivante dans le répertoire /lib/active_resource/extend/ ne pas oublier de dé-commenter le ligne
    "config.autoload_paths += %W(#{config.root}/lib)" dans config/application.rb

    module ActiveResource #:nodoc:
      module Extend
        module AuthWithApi
          module ClassMethods
            def element_path_with_auth(*args)
              element_path_without_auth(*args).concat("?auth_token=#{self.api_key}")
            end
            def new_element_path_with_auth(*args)
              new_element_path_without_auth(*args).concat("?auth_token=#{self.api_key}")
            end
            def collection_path_with_auth(*args)
              collection_path_without_auth(*args).concat("?auth_token=#{self.api_key}")
            end
          end
    
          def self.included(base)
            base.class_eval do
              extend ClassMethods
              class << self
                alias_method_chain :element_path, :auth
                alias_method_chain :new_element_path, :auth
                alias_method_chain :collection_path, :auth
                attr_accessor :api_key
              end
            end
          end  
        end
      end  
    end
    

    dans les modèles il faut inclure le module

    class Post < ActiveResource::Base
      include ActiveResource::Extend::AuthWithApi
    
      self.site = "http://application.localhost.com:3011/"
      self.format = :json
    
      self.api_key = 'jCxKPj8wJJdOnQJB8ERy'
    
      schema do
        string  :title
        string  :content
      end
    
    end
    

    Et le tour est joué !

     

  13. ActiveResource et Json

    J’ai voulu mettre en place un client ActiveResource qui consomme du :json

    J’ai créé un service de Blog simple

    La migration :

    class CreatePosts < ActiveRecord::Migration
      def self.up
        create_table :posts do |t|
          t.string :title
          t.text :content
          t.timestamps
        end
      end
    end
    

    Le modèle :

    class Post < ActiveRecord::Base
    end
    

    Le contrôleur :

    class PostsController < ApplicationController
    
        respond_to :html, :xml, :json
    
        def index
            @posts = Post.all
            respond_with(@posts)
        end
    
        def show
            @post = Post.find(params[:id])
            respond_with(@post)
        end
    end
    

    Le client ActiveResource

    class Post < ActiveResource::Base
    
      self.site = "http://application.localhost.com:3011/"
      self.format = :xml
    
      schema do
        string  :title
        string  :content
      end
    
    end
    

    Jusque là tout est ok et fonctionne très bien, alors je décide de passer en Json

    Le client ActiveResource

    class Post < ActiveResource::Base
    
        self.site = "http://application.localhost.com:3011/"
        self.format = :json
    
        schema do
          string  :title
          string  :content
        end
    
    end
    

    Au moment de lister les posts j’obtiens le message suivant :

    ActionController::RoutingError in Posts#index
    
    Showing /.../app/views/posts/index.html.erb where line #... raised:
    
    No route matches { :action=>"show", :controller=>"posts", :id=>
    #<Post:... @attributes={"post"=>#<Post:... 
    @attributes={"content"=>"...","id"=>1, "title"=>"..."}, 
    @prefix_options={}>}, @prefix_options={}>}
    Extracted source (around line #...):  
    

    En fait le service de Blog renvoit le Json avec le :root comme il se doit, cependant ActiveResource ne le gère pas…

    Vous devez ajouter la directive suivante dans le client :

    Le modèle :

    class Post < ActiveRecord::Base
        self.include_root_in_json = false
    end
    
     

  14. Article intéressant sur la conséquences d’Hadopi (entêtement du gouvernement et des majors)

     

  15. Application de Checkin

    Voilà une petite application ad hoc pour permettre d’émarger votre présence dans un lieux commun. L’idée vient de l’espace de co-working que je fréquente La Cantine à Toulouse qui effectue un émargement manuel. Ce qui peut paraitre surprenant ou décevant pour une association qui évolue autour des acteurs du numériques de la région, mais money is money et time is money, en clair il faut non seulement du temps, des ressources mais aussi de l’argent pour mettre en place une application aussi simple que celle-ci et qui ne ramène pas d’argent … Dur dilemme !

    Ce que fait l’application en quelques points :

    Connexion

    Lorsque que le co-worker chargera la page du portail il sera obligé de se connecter, sa connexion peut se faire via la délégation d’authentification, cependant un compte utilisateur devra être créé et la délégation devrait être couplée au compte. Si tel n’est pas le cas l’authentification renverra sur la page de compte.

    Crédit

    Le co-worker doit posséder des crédits pour pouvoir émarger. Un crédit permet d’émarger une demi-journée.

    Émargement

    Une fois authentifié avec un compte crée le co-worker pourra émarger. Il se verra proposer un écran avec un bouton émarger la matinée ou émargé l’après midi en fonction de l’heure, et une proposition pour l’émargement de la journée directement. L’émargement aura un état «disponible» et une heure de début et de fin de plage correspondant à la matinée ou l’après midi en cours.

    Mon Compte

    Le co-worker pourra visualisé la page de son compte, modifier ses informations, connaitre son solde.

    Consultations des fiches des co-workers

    En se connectant au portail de n’importe où le co-worker pourra accéder à l’ensemble des fiches des co-worker inscrit. Il pourra aussi voir les personnes ayant émargées et donc censées être présente dans l’espace de co-working. Cependant afin de limiter l’utilisation des informations à des fins autre que la communication naturelle que le co-working est censé amener les informations visible entre les co-worker se limiterons à la photo et au prénom. Afin d’avoir accès à plus d’informations le co-worker pourra effectuer une demande, si cette demande est accepter les 2 profils pourrons mutuellement avoir accès à l’ensemble de leurs informations.

    Consultations des co-workers présent

    Accès a la page des co-workers, un filtre permettra d’afficher les personnes présentes en fonction de la plage horaire.

    Notification de présence

    Un co-worker pourra être averti de la présence d’un autre co-worker à La Cantine. Cependant cette fonctionnalité ne sera offerte qu’aux co-workers étant déjà en relation.

    Scénario

    Le co-worker est invité à s’authentifier, il est inviter à compléter son compte si cela n’est pas fait, puis il est redirigé sur la page de compte où il peut effectuer son checkin, une fois le checkin il est redirigé sur la tronbinoscope des personnes présente.

    L’application est disponible sur Github, toutes contributions sont les bienvenues !!!