Friday, October 5, 2012

Patron : Fabrique (factory)

Le patron Fabrique (Factory en anglais) est un patron de type conception.

Ce patron contient une classe qui fait appel à une fabrique pour créer des objets sans connaitre la classe exacte de ces objets. Pour déterminer la classe exacte, un paramètre est passé lors de l'appel.



Description des classes :

  • Fabrique : la fabrique en charge de créer les objets selon le paramètre recu 
  • Race : classe abstraite 
  • Humain, Orc, Elf : classes fille de Race 
  • Jeu : classe principale qui ne se preocupe pas de quel type de race sont les objets qu'elle manipule 



Dans l'exemple ci-dessous, la classe Jeu fait appel à la classe Fabrique. La classe Jeu ne connais pas les sous-classes de Race.
La responsabilité de créer le bon objet est laissé à la classe Fabrique. Cela fait moins de ligne de code pour la classe Jeu.

Une fois les objets personnagePrincipal, ennemi et ami crées, la classe Jeu traite ces objets comme des objets de type Race.


Jeu.java
public class Jeu {
 
 public static void main(String[] args) {
  Jeu jeu = new Jeu();
  jeu.jouer();
 }
 
 public Jeu() { }
  public void jouer() {
  Fabrique fabrique = new Fabrique();
  
  Race personnagePrincipal = fabrique.getRace("humain");
  action(personnagePrincipal);
  
  Race ennemi = fabrique.getRace("orc");
  action(ennemi);
  
  Race ami = fabrique.getRace("elf");
  action(ami);
 }
 public void action(Race joueur) {
  //on ne se préocupe pas si "joueur" 
  //est un humain ou un orc ou un elf
  joueur.parler();
 }
}
Race.java
public abstract class Race {
  abstract void parler();
}
Humain.java
public class Humain extends Race{
 public Humain() {}
 
 public void parler() {
  System.out.println("Je suis un humain!");
 }
}
Orc.java
public class Orc extends Race{
 public Orc() {}
 
 public void parler() {
  System.out.println("Grrrrrr");
 }
}
Elf.java
public class Elf extends Race{
 public Elf() {}
 
 public void parler() {
  System.out.println("Je suis un elf!");
 }
}
Fabrique.java
public class Fabrique {
 public Fabrique() { }
 
 public Race getRace(String type) {
  Race race;
  
  // ...
  // par exemple: doit faire des trucs 
  // compliqués ici avant la creation d'objet 
  // (verification, initialisation, etc.)
  // ...
  
  if ("humain".equals(type))
   race = new Humain();
  else if ("orc".equals(type))
   race = new Orc();
  else if ("elf".equals(type))
   race = new Elf();
  else
   race = null;
  
  return race;
 }
}



Et sans la Fabrique...

L'exemple est très simple, donc ce n'est pas évident de prouver que sans l'utilisation de ce patron, le code devient plus complexe. Mais je vais essayer.
Voici maintenant le meme code sans la fabrique.
public class NoFactory {

 /**
  * @param args
  */
 public static void main(String[] args) {
  NoFactory noFactory = new NoFactory();
  noFactory.start();
 }
 public NoFactory() { }
 
 public void start() {
  
  // ...
  // par exemple: doit faire des trucs 
  // compliqués ici avant la creation d'objet 
  // (verification, initialisation, etc.)
  // ...
  
  Race personnagePrincipal = new Humain();
  action(personnagePrincipal);
  
  Race ennemi = new Orc();
  action(ennemi);
  
  Elf ami = new Elf();
  action(ami);
 }
 
 public void action(Race joueur) {
  // on ne se préocupe pas si "joueur" 
  // est un humain ou un orc ou un elf
  joueur.parler();
 }
}
Deux choses :

  1. la classe NoFactory doit maintenant s'occuper de faire des trucs compliqués (exemple: verifications, initialisation,etc.) avant la creation des objets 
  2. la classe NoFactory doit connaitre le type exacte des objets. 


J'ai certainement fait des fautes ou écrit des choses pas clair, donc n'hésitez pas laisser un commentaire. Lien Wikipedia : Fabrique

Thursday, May 24, 2012

Rails NoMethodError on calling Module

So I had to create a module and call one of the function from a controller.

After looking on Google I could find this post on RailsForum.
Basically, you have to do that:
in lib/something/task.rb
module Task
  def my_method
    "hello there"
  end
end
In the application controller
class EnrolmentController < ApplicationController
  include Task

  def index
    my_method
  end
end
Please note the difference, my module is in "lib/something/Task.rb".  The file is not at the root of lib.

Problem
Why I still have "NoMethodError"?

Solution
Pretty easy, you have 2 steps to do. First you need to add this in config/application.rb
config.autoload_paths += Dir["#{config.root}/lib/**/"]

But if you still try it, it's not working... Well, in fact you have to restart your server! When you add a directory and files in config folder, you have to restart your server (same for the translation file)
And that's it!

Friday, April 13, 2012

Rails 3 Facebook Ajax picture

My rails 3 website shows a list of friends, and you can click on "next" to see the 10 next friends.
I'm using this :

    

Problem : I can load dynamically and see my next friends but not their  facebook profile pictures. Why?

Solution : In fact, you just need to "refresh" (re-parse) the element.
Do not use FBML because it will be deprecated soon.
Instead, use FB.XFBML.parse();

For example, in my action (who has been called by using :remote => true), it returns a ".js.erb" file.
In this .js.erb file, I append my friends, and at the end I just do FB.XFBML.parse(XX), where XX is the name of the section that I want to "refresh"/"re-parse".

and that's it !

rails 3 and jquery tabs

Recently, I'm working on a Ruby on rails website and I wanted to display some tabs.
Now, Rails 3 uses jquery, fine so let's search "jquery tabs" on Google, and I could find Jquery UI.
Oh and there is a "tab" widget. Perfect!
How to insert tabs in my website? Ok,  let's check on Google! I could find many websites saying that I should download the javascript files from the website and include them like that :
<%= javascript_include_tag "jquery_min.js ....
So I did it, but it didn't work...

Problem: how to use this widget ?

Solution : in fact, you don't need to download any javascript files! You just need a CSS file!
Here is more details:
Be sure to have : gem 'jquery-rails' in your Gemfile.
In application.js,  you need this :
//= require jquery
//= require jquery_ujs
(with these 2 lines above, you're importing Jquery, that's why you don't need to download any extra javascript files!)

Then, try to find a "jquery.ui.tabs.css". You can find it on the Jquery UI website.
Here is one ugly css for example (in case you can't find it):
.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; }
.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative;  top: 1px; margin: 0 .2em 1px 0; padding: 0; white-space: nowrap; }
.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; }
.ui-tabs .ui-tabs-nav li.ui-tabs-selected { border: medium solid Orange;margin-bottom: 0; padding-bottom: 1px; }
.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; }
.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; border: medium solid Orange;}
.ui-tabs .ui-tabs-hide { display: none !important; }

In application.css.scss add this : @import "jquery.ui.tabs";

And now copy/paste the example code from Jquery UI Tabs page, and that's it !

Sorry, I should write more clearly with more details, but I don't have time now!

Saturday, February 18, 2012

Delete mkv file from windows

I had a mkv file that I wanted to delete. So I opened the explorater, go to the folder, right click on the file and Delete. But then I have the error (something like that) : you can't delete this file because another process is using it.

Well, but I'm sure no other process is using it !

Problem 
How to delete mkv files ?

Solution
Well, I found this solution on Internet and it's easy. In fact, "explorer.exe" is using the mkv file.

Open a command prompt window (click here for more info).
Go to the folder where the mkv file is (keep the prompt open, we will use it later!). You can use the command "cd myVideos" for example. (click here for more info).

Open the Task Manager by pressing : ctrl + alt +  suppr. (other possibilities)
Choose "start task manager"
Open the "processes" tab
Select "explorer.exe" (be sure sure to select "explorer.exe" !!)
Click on "end process". Your icons and task bar will disapear, but that's ok. (don't close the task manager we will need it later).

Go to the prompt again and delete the file (del video.mkv).

Go to the task manager
Open the "application" tab
Click on "New Task...".
Enter "explorer.exe" (without double quotes!) and click "OK". Then your icons and task bar will appear !

And that's it

Wednesday, February 1, 2012

web2py plugin_wiki tag

In my website, I want the user to be able to add tags to a picture. I'm happy because I can see that there is a plugin in web2py to do that.
Have look here: web2py Plugin but, it said that the plugin tag is kind of deprecated and we have to use the plugin_wiki.
Attention: some of the plugins listed here are old (in particular jqgrid, comments, tagging, modal, dropdow, attachments, latex, flash video and deprecated). Newer versions have been incorporated into plugin_wiki.
So I watched the video explaining how to use the plugin_wiki. But I don't want to create pages using the plugin_wiki, I just want to add tags!

Problem 
How to just add tags to my view file without using the wiki interface ?

Solution 
In fact it's really easy. In the view file just add this : {{=plugin_wiki.widget('tags',table='thumbnail',record_id=thumbnail.id)}}

thumbnail is the name of my table.
thumbnail.id is the id column (as you can guess)

Then, if you want to modify the behaviors you can modify the plugin_wiki controller : controllers/plugin_wiki.py, there is an action for each plugin, so you'll find an action called "tags".
And you can modify the "view" of a tag : view/plugin_wiki/tags.html

That's it !

Saturday, January 21, 2012

Web2py - remove the "delete" check box

In web2py, the form displayed  to update form containing an input file is like this :
name + input text + "browse" button + [file + delete check box]

Problem : how can I remove this "delete" check box ? Because the image is required. If I check the value is not null, it returns false, because the value is empty.

Solution : it's really easy. In your file db.py just add: requires=IS_NOT_EMPTY
Field('data', 'upload',requires=IS_NOT_EMPTY())

And that's it !