Promine

Nossas idéias para você…

Hey guys, as promised by DHH (on his post during week), Rails 3.0 was released!

This version has a huge amount of changes:

  • New Action Mailer: It is all controller now. Forget about creating a model!
  • Routes: The syntax was completely remade to be more a REST-based compliant.
  • Switch easily to your preferred JS library: Now changing from Prototype to JQuery or vice-versa it is supposed to be very straightforward.

You can see the complete list of changes on the official release announcement post.

Let’s try it out! Awesome work RoR team!

Popularity: 2% [?]

Oi pessoal!

Faz um bom tempo que não posto por aqui. Hoje, eu gostaria de conversar sobre um assunto um tanto polêmico e é necessário um pouco de coragem para falar. Claro, isso não me faz melhor. Hoje, eu comprei um DVD de um filme que é um clássico pra mim: Os Intocáveis. Sim, paguei R$ 20,00 por um filme que eu poderia baixar. Por que eu fiz isso? Por comodidade. Isso mesmo. Alguém já disse isso, eu não lembro. Mas nós pagamos por conveniência e não por acesso ao conteúdo. Eu pago em média R$ 120,00 mensais para acessar a rede a 10MB. É muito facil baixar conteúdo e poderia ter feito o download rapidamente, mas seria trabalhoso. Não é preguiça. Olha quanto trabalho ia ser…

Teria de procurar o filme numa qualidade razoável, quando encontrasse e levaria 2h para baixar, começaria a maratona para buscar uma legenda sincronizada. Caso não encontrasse, teria de baixar um programa para sincronizar, ver tutoriais para relembrar o procedimento para tal. Até aí, já teria levado umas 3,5h (bem otimista, nã0?) ou mais. Enfim, eu iria ver o filme. Para alguns de nós que têm familiaridade com tecnologia é até divertido isso. Mas pense nas pessoas que acham que o Internet Explorer é a própria Internet. Elas não sabem e nem querem ter esse trabalho. Minha sogra tem anotado num caderno ao lado do micro, todos os passos para postar fotos no Orkut – e quase sempre ela o consulta.  Minha mãe – com 3 meses de experiência de acesso à rede – não consegue enviar email. Eu já ensinei várias vezes. Burra? Não, claro que não. Primeiro por que ela é minha mãe segundo, por que tudo isso não faz o menor sentido pra ela. “Jonas, tudo nesse bicho é muito difícil! Não tem um jeito mais fácil?”

O que eu quero dizer com isso: que as coisas estão caminhando – e precisam – para a comodidade. Tem que ser fácil e conveniente. Na verdade não pagamos por acesso ao conteúdo. O fazemos porque queremos rápido e fácil! Os modelos de negócio já existentes precisam se adaptar a essa nova regra. Bom, agora é com você… concorda, não? então comenta. Vamos discutir, será um prazer!

Popularity: 5% [?]

Yesterday,  I was trying to customize my Gmail signatures, but unfortunately, the Gmail does not have a complete rich text editor yet.

I’d like to put an image (logotype) and my personal information side by side, as you can see below.

However, when you insert an image through this text editor, you have no option to set the image CSS to “float: left;”, neither graphically (WYSWYG) nor textually (inserting raw HTML code).

So, I had to trick a little and use Firebug. Firebug is a so damn good Firefox plugin that provides you a lot of features, like CSS and HTML inspection and edition.

After installing the plugin, click on the icon on the right bottom corner of your browser and enable all panels. After that, click on the HTML tab and after on the blue arrow icon to enable the selection feature.

At Gmail Settings page,  click on the box that holds the signature. Firebug shows the HTML of the selected box. Click on Edit (below HTML tab button) and enjoy it. You can set any HTML you want and set inline styles.

After editing the HTML on Firebug, click on Save Changes on Gmail. Enjoy your new signature! See ya.

Popularity: 50% [?]

Agora a pouco foi anunciado o Rails 3.0 Release Candidate. Atrasou um pouco esse anuncio, que já era esperado desde a RailsConf, mas o que importa é que foi lançado e é hora da gente aproveitar pra testar, relatar e consertar os últimos bugs. De acordo com o próprio DDH, em algumas semanas teremos a versão final.

Já é possível encontrar vários artigos e screencasts sobre o Rails 3 beta (1, 2, 3 e 4). Segue abaixo uma lista de sites interessantes sobre Rails 3:

  1. RailsGuides
  2. RailsCasts
  3. EnvyLabs
  4. RailsPlugins

Mais informações direto do blog do rails.

Em breve estaremos postando aqui as experiências da Promine com o Rails 3. Abraços.

Popularity: 36% [?]

Before publishing your Rails application, it is very important to care about performance. When we think about performance some issues like caching and compression come up to our minds. A great Firefox plugin to analyze and improve your web app perfomance is the YSlow one integrated with the Firebug. With YSlow you can see which are your web site bottlenecks. A very common and useful action you can take is reducing the number of HTTP requests and minifying javascript and stylesheet files.

According to the HTTP rules, each web site file (like images, javascript, …) is sent to the browser on a different response message. So, it’s quite straightforward to think about putting somehow many files together to reduce the number of responses. Using the asset_packager plugin, you can run a rake task to aggregate and minify stylesheets and javascripts. I do advise you to use this plugin, but take a look at the following tips in order to save some time and avoid issues when publishing your web site.

  1. Remove @charset at-rule: Some IDEs automatically add a @charset “iso-8859-1″ line, for example, at the top of stylesheet files. When you run rake asset:packager:build_all that line may broke the generated packaged file.
  2. Avoid/Remove @import at-rule: The @import CSS rule allows you to include external stylesheets in your document. However, you can mess your site layout up if you use it, since it doesn’t follow the loading order you defined on the config/asset_packages.yml. If you want to reuse files, split your files as you prefer and group them on the asset_packages.yml.
  3. Avoid compressed javascripts: The most common js libraries has a minified version. As asset_packager compresses js files, avoid re-compressing those files. If you prefer minified files, you shouldn’t include them into the asset_packages.yml.
  4. Test your app on the production environment: Before publishing your app, test it on the production environment (script/server -u RAILS_ENV=production). You can find some layout bugs.

That’s it. If you have any further tip, please, let me know, leave a comment.

Popularity: 3% [?]

Oi pessoal!

O motivo que me leva a escrever é dizer o que penso e botar a minha cara a tapa mesmo. Bom, cliché a parte, vamos ao post.
Nesta semana, recebi um e-mail de uma empresa de produtos de informática. Não foi spam. Eu tomei a iniciativa de me inscrever para receber informações da tal empresa. Apenas para ficar monitorando o mercado. Qual não foi minha supresa quando eu abrir a mensagem e me deparei com uma imagem de 1440 pixels de largura… meu Deus! Quebrou todo o meu gmail.

Claro, podemos até pensar que a imagem era gigantesca por um propósito especial mas… não. Podia ser muito menor. Pelo menos uns 80% menor. Comecei a pensar sobre isso e a ficar mais atento à abordagem adotada por algumas empresas nas peças de e-mail marketing que eu recebo. Foram muitos os pontos de melhoria (sem mais delongas, defeitos mesmo). Dimensões exageradas, uso de imagem quando um texto seria melhor, tratamento sofrível das imagens, link universal (sabe quando tu recebe um e-mail com várias ofertas, não importa em qual você clique, sempre vai pra mesma página e lá fica perdido) e que é pior, Opt-out muito difícil de ser encontrado.

Vamos usar as novas mídias respeitando e explorando o potencial de cada uma delas. Do que adianta usar e-mail se você faz como se fosse um cartaz? Por que não pensar no perfil do seu público e checar se o que você ver lindo na sua tela não vai ser uma catástrofe no do seu cliente?

Bom, é isso!

Popularity: 36% [?]

As I promissed last week, here it is the simple tabs, jQuery version. It follows basically the same idea, but adapted to use the jQuery library.

Try it out:

Download Code

Configuration

  1. Include jquery (tested 1.4.2)
  2. Include promine.simple.tabs.js
  3. Create tab menu and set the menu html id into the promine.simple.tab.js
  4. Important: menu item prefix must be the same the tab content prefix. Ex.: profile_menu -> profile_content

Javascript

$(window).ready(function () {
  initTabs('#tabs');
});
 
function initTabs(tabs_menu){
  if($(tabs_menu).length > 0){
    // listen to some events to implement a tab menu behavior
    $(tabs_menu + ' span').each(function(i, elem){
      $(this).click(function(){
        var blockName = "";
        var auxArray = [];
	$(tabs_menu + ' span').each(function(j, tab){
          // get the corresponding block name according to the tab id
          auxArray = $(this).attr("id").split("_");
          auxArray.pop();
          blockName = (auxArray.length > 1) ? auxArray.join("_") : auxArray[0];
          blockName += "_content";
 
          if($(this).attr("id") == $(elem).attr("id")){
            $(this).addClass("selected");
            $('#' + blockName).show();
          }else{
            $(this).removeClass("selected");
            $('#' + blockName).hide();
          }
        });
      })
    })
  }
}

HTML

<!-- menu -->
 
<div id="tabs">
  <span id="javascript_menu" class="selected">Javascript</span>
  <span id="html_menu">HTML</span>
  <span id="css_menu">CSS</span></div>
 
 
<!-- content -->
 
<div id="javascript_content">Javascript content</div>
 
 
<div id="html_content" style="display: none;">HTML content</div>
 
 
<div id="css_content" style="display: none;">CSS content</div>

CSS

#tabs{
    width:100%;
    border: solid #CCC;
    border-width: 0 0 1px 0;
    height: 26px;
}
 
#tabs span{
    display: block;
    width: 150px;
    float: left;
    height: 20px;
    text-align: center;
    padding: 6px 5px 0 5px;
    cursor: pointer;
    font-weight: bold;
}
 
#tabs span.selected{
    border: solid #CCC;
    border-width: 1px;
    padding: 5px 4px 0 4px;
    border-bottom-color: #fff;
    background: #fff;
}

Popularity: 69% [?]

Last week I was looking for a stupidly simple tabs system. I didn’t need anything other than toggling some divs after clicking on a menu item and making no change in the javascript if I’d like to add a new tab. After googling for a while, I found some interesting codes but none of them were as simple as I would like. I’d like to include only a 1-kb javascript file to make things work. So, I created my own solution :) . Please: don’t expect to see an outstanding and revolutionary code, because that is only a simple tab system and probably somebody has already done something like that. This week I wrote the Prototype version. Next week I’ll rewrite it using Jquery library.

Try it out

Download Code

Configuration

  1. Include prototype (tested 1.6.1)
  2. Include promine.simple.tabs.js
  3. Create tab menu and set the menu html id into the promine.simple.tab.js
  4. Important: menu item prefix must be the same the tab content prefix. Ex.:  profile_menu -> profile_content

Popularity: 52% [?]

Hi guys, this my first post in English and I decided to do this because in this way I can help more people. I’ve been working in a project that we have to develop a web application to manage licenses, to create serial numbers and to validate them. As the classes for generating and validating serial number were written in Java, we decided to develop in Grails (which is much more productive than JSP, Servlets, Struts and other stuffs like these). However (when somebody says ‘However’ or a similar adverb, watch out! :P ), when I started developing in Grails, I felt a bit (being euphemistic) disappointed. I’m a Rails developer, so it was natural to compare Grails with Rails. I missed lots of awesome features (like migrations, helpers, rjs, …) that Rails gives to us, programmers, when I developed in Grails for the first time. Nevertheless (watch it out!), part of that frustrating first experience with Grails was due to lack of knowledge. After studying for some days and googling a lot, I took note some tips that if had read before, I would have had a better first impression of this good framework (it is not awesome because Rails is, and Rails is much more mature and complete).

  1. Grails is not a Rails with Groovy: If you are a RoR programmer, keep in mind that Grails is very different of Rails. You will miss a lot of great Rails stuffs, but you can find fun stuffs on Grails also. Groovy is much more straightforward than Java (in my opinion), but that is not as productive as Ruby. So, try to forget about Rails for a while when you start programming in Grails.
  2. Read the Groovy Quick Start Guide: I do advise you to read the Quick Start Guide. You need only 5-10 minutes to do it. If you have a bit more time, take a look at the Getting Started Guide. It is also a guide very useful. When you need a reference, this can be helpful.
  3. Read the Grails User Guide: The Quick Start and User Guide will give you enough knowledge to start a Grails project.
  4. Take a look at Grails plugins before creating your own: There are a lot of great plugins in the Grails Plugin page. Before starting your project, take a brief look on the existing plugins and try some of them. You can also help the Grails community improving some of them.
  5. Install the plugin magic-numbers: If you are a Ruby programmer, probably you would like doing things like 2.days or 3.day.ago. You can do these things, only installing the magic numbers plugin. For instance, if you want to proceed only if an entry was created during the last three days, you can do the following:
    if (3.days.ago.toDate() > dateCreated) {
        // do something
    }
  6. Unique constraint is case sensitive: This unique constraint really pissed me off. I’d like to add a unique constraint (basically a constraint is used to validate and to define the table structure) that was also case insensitive. I wouldn’t like to have two different entries whose name property were Promine and PROMINE. I thought it would be very straightforward, but it won’t. The only way I figured out to put the code to work properly was the following one:
    name(blank:false, maxSize:255, validator: { val, obj ->
            // check if it is unique with case insensitive
            def app = Application.withCriteria{
                ilike('name', val)
                if(obj.id){
                    ne('id', obj.id)
                }
            }
     
            return (app) ? "default.not.unique.message" : null
        })

    I found some solutions but none of them worked properly when editing a record, since they did not check the entry id.

  7. Order by nested properties: If you generate a crud and change the list.gsp view including (or changing) some sortableColumns, probably you face a boring problem: sort nested properties. If you look the Sortable Column Tag page you will see a ’solution’: using criteria instead of list. Unfortunately, it doesn’t work if you want to sort by a nested property of a nested property. For instance, suppose you have these entities Application(id, name, code), ApplicationType(id, applicationId, name) and License (id, serialNumber, applicationTypeId). In the license list page, you cannot have sortable column Application Name, unless you install the GORM Labs plugin. This plugin, among other cool improvements, provides us a feature to sort by nested properties separated by dot, like order(‘applicationType.application.name’, ‘asc’). See the code below.

    Controller

    def list = {
        // sets some default values if they were not passed as argument
        if (!params.max) params.max = 10
        if (!params.offset) params.offset = 0
        if (!params.sort) params.sort = "id"
        if (!params.order) params.order = "asc"
     
        // gets the records via criteria in order to enable sortableColumn
        // for nested properties
        def licenseList = License.withCriteria {
            maxResults(params.max?.toInteger())
            firstResult(params.offset?.toInteger())
            // order the results using the gorm labs plugin functionality
            order(params.sort, params.order)
        }
     
        [licenseInstanceList: licenseList]
    }

    View

    <g:sortableColumn property="applicationType.application.name" title="Name" />
  8. Create your own tag libs: As a Rails programmer, I usually create helper methods to organize my view code and to adhere the DRY philosophy. Let’s consider that tag libs on Grails acts_as_rails_helper. You can create your own tag libs and create methods to be invoked statically from views and controllers, for instance. See below an example of a basic tag lib:
    class UtilTagLib {
        static String cleanSerialNumber(String sn){
            return (sn =~ /[^0-9A-Z]/).replaceAll("")
        }
    }
  9. discard() method can save your life: Grails can save an object even if you don’t have an explicit call to the method save(flush: true). Sometimes weird things happen, and when they happen, remember that there is the discard() method. According to the Grails wiki, the discard method “discards any changes that have been made during an update. Note that this method will not clean or reset the object with the original values it will just prevent it from being automatically saved by Grails.
  10. Interceptors can be very useful and elegant: An interceptor is a method called before or after some pre-defined (or all) actions of a controller. If you need to execute a set of commands before some (or all) actions, don’t repeat yourself, create an interceptor. Declaring a before interceptor is very simple:
  11. Execute before all actions

    def beforeInterceptor = {
       // do something
    }

    Execute before all actions, but index

    def beforeInterceptor = [action:this.&setEvents, except:'index']
     
    def setEvents() {
       // do something
    }

    Execute only before save action

    def beforeInterceptor = [action:this.&normalizeData, only:'save']
     
    def normalizeData() {
       // do something
    }

Popularity: 100% [?]

Nos últimos dias a Promine fechou contrato com mais 3 novos clientes: Deputado Sarto, Livraria Livro do Concurseiro e Santuário Rainha do Sertão.

Deputado Sarto: Será desenvolvido um site pessoal totalmente novo para o Deputado Estadual José Sarto. Utilizando o CMS da Promine, os assessores do gabinete poderão incluir notícias, fotos, projetos de lei, moderar comentários, incluir compromissos na agenda e criar tweets sem ter que entrar no Twitter.

Livraria Livro do Concurseiro: Site de comércio eletrônico completo para venda de livros e apostilas para concursos em geral. Com um gerenciador completo das vendas e produtos, a Promine fornece todos os recursos necessários para que o administrador gerencie a loja como desejar.

Santuário Rainha do Sertão: Site do Santuário Rainha do Sertão e da Casa de Retiros em Quixadá-CE com informações gerais para os visitantes que desejam se hospedar, fazer romarias, relatar graças alcançadas, entre outros. O CMS da Promine irá facilitar todo o processo de inclusão de conteúdo.

Durante os próximos 2 meses estaremos interagindo constantemente com nossos clientes para que o produto final seja diferenciado. Acesse nosso portfolio para conhecer todos nossos clientes. Até a próxima.

Popularity: 19% [?]