HashCode

An organizer of symbols

Archive for the ‘Rails’ Category

Pixily hiring RoR guy

Wednesday, December 9th, 2009

Pixily hiring RoR guy

Ops! RailsTree, de novo?

Monday, November 10th, 2008

Puts! Foi mal Akita e Carlos esse projeto é de mil novecentos e Titanic mas obrigado por mencionar. Eu repostei ele sem querer.

O post real está aqui

RESTful - Parent Load, com método preload

Friday, August 29th, 2008

Para quem usa RESTful e Nested Resources existe uma ação de carregamento do objeto pai na maioria dos controllers filho.

Se você não entendeu nada do que eu falei, dê uma lida em
RESTful Rails Development, by Ralf Wirdemann & Thomas Baustert

Por exemplo tenho dois models um Person e o outro Personality sendo que Person tem uma Personality e Personality pertence a Person.
Ficando assim o relacionamento no AR

#app/models/person.rb
class Person < ActiveRecord::Base
  has_one :personality
end
#app/models/personality.rb
class Personality < ActiveRecord::Base
  belongs_to :person
end

e as rotas desta forma

ActionController::Routing::Routes.draw do |map|
  map.resources :personalities, :belongs_to => :people, :singular => "personality"
  map.resources :people, :has_one => :personality
end

Ok até agora. “Feitisso” podemos criar um registro Person via /people/new e depois criar um registro Personality via /people/1/personality/new
Quando for criado o novo registro Personality o id do pai(Person) vai como parametro

params[:person_id]

Então você já deve ter visto muito a estrategia de carregamento do objeto pai em uma variável de instância via filtro, em um construção do tipo abaixo:

class PersonalitiesController < ApplicationController
  before_filter :get_person

  private
  def get_person
    @person = Person.find(params[:person_id])
  end

end

Portando antes de executar a action o pai é carregado via filtro.

Para evitar está estrategia que estava repetindo em quase todos meus controllers crie o método preload.
Com preload posso ter uma contrução mais clara e com o mesmo efeito. Então agora posso fazer assim

class PersonalitiesController < ApplicationController
  preload :person
end

Podemos também utilizar include, order, limit, etc

class PersonalitiesController < ApplicationController
  preload :person, :include => :personality
end

Ou até especificar em quais actions o preload será utilizado

class PersonalitiesController < ApplicationController
  preload :person, {:include => :personality}, {:only => [:create]}
end

Olha a origem da mágica

class ApplicationController < ActionController::Base
  def self.preload_object(name,options,filter_options={} )
    before_filter(filter_options) do |controller|
      controller.instance_variable_set("@#{name}", name.to_s.camelize.constantize.find(controller.params["#{name}_id"], options))
    end
  end
end

Apenas um método de classe dentro do ApplicationController e um pouco de meta programação.
Agora vou tentar explicar o médodo preload.

Começando por

  name.to_s.camelize.constantize

o name vem como Symbol no nosso caso :person, então temos

name.to_s  		#=> "person"

O método camelize analiza o conteúdo da String e adapta ao padrão de nome de classes utilizadas em Ruby, exemplo “foo_bar” camelizado passa a ser “FooBar”.

name.to_s.camelize #=> "Person"

Invocando a constante

name.to_s.camelize.constantize #=> Person

ou poderia utilizar

Object.const_get name.to_s.camelize

Já que tenho a classe Person utilizo o find passando o padrão pai_id.

O bloco do before_filter passa um yield do controller, precisamos do controller neste escopo pois estamos em um contexto estático, por conseguinte apenas params[:pai_id] não é visível então utilizei controller.params[:pai_id]

E por último criar a instância @pai apontando para o retorno do Person.find, vou dar um zoom no código :)

class ApplicationController < ActionController::Base
  def self.preload_object(name,options,filter_options={} )
    before_filter(filter_options) do |controller|
		  parent_id = controller.params["#{name}_id"]
			find_return = name.to_s.camelize.constantize.find(parent_id)
			controller.instance_variable_set("@#{name}", find_return)
    end
  end
end

Ou você prefere a versão One-Line-Brain-Fucker?

class ApplicationController < ActionController::Base

  def self.preload_object(name,options,filter_options={} )
    before_filter(filter_options) { |controller| controller.instance_variable_set("@#{name}", name.to_s.camelize.constantize.find(controller.params["#{name}_id"], options)) }
  end

end

Mais DRY, mais DRY …

Executive IT Meeting em Goiânia

Friday, October 26th, 2007


Gostaria de Convidar a todos a participarem do Executive IT Meeting l em Goiânia, 29..31 de outubro de 2007.
Vou representar a comunidade(espero ser capaz) :)
O meu amigo Alexandro Lima fez uma Charge para o evento.

palestra_rubi_contec.jpg

Nossa participação será no dia 31 na parte da tarde:

Palestra: Linguagem Ruby - Minerando e Lapidando.
Filosofia, idiossincrasia e pragmática da linguagem.

Tutorial: Ruby on Rails - Overview sobre o Framework do Ano.
Desenvolvendo um aplicação MVC em Rails.

Espero vcs lá hein! :)

Rails Tree Release 0.8.5

Friday, August 10th, 2007

Nova versão do plugin railstree com criação via Hash e bugfix RSS.


  tabelas1=%w(starttelephony startvoip customers  gateways)
  tabelas2=%w(teste1 teste2 ) 

  d1=Node.new(:label => "radius", :icon => "/images/data.png", :open => true)
  d2=Node.new(:label => "teste", :icon => "/images/data.png", :open => false)

  tabelas1.each do |t|
    no=Node.new(:label => t, :icon => "/images/table_sql.png")
    d1 << no
  end

  tabelas1.each do |t|
    no=Node.new(:label => t, :icon => "/images/table_sql.png")
    d1 << no
  end

  tabelas2.each do |t|
    no=Node.new(:label => t, :url => 'link aqui', :icon => "/images/table_sql.png")
    d2 << no
  end

  tr = Tree.new(:label => "Databases[solaris]")
  tr << d1
  tr << d2
Version Download Howto Repository
0.8.5 rubyforge.png

 

 

RailsTree 0.8.5

Tuesday, July 10th, 2007

Estava procurando uma tree para utilizar em rails e não achei, aí migrei a tree que tinhamos desenvolvido baseado no javascript do Geir Landr[2003] do formj para um plugin rails.
Exemplo de árvore dos dois estilos por padrão.
Gnome Style(default)

Explorer Style

tree2.png

Mac X/Acqua Style
Me mande que coloco aqui :-)
Anatomia
Após a instalação o railstree adiciona os seguintes arquivos no RAILS_ROOT

/lib/node.rb                 # o nó
/lib/tree.rb                 # a tree que também é um nó(raíz)
/public/images/tree/*.gif    # imagens(pasta,documento,etc)
/public/javascripts/tree.js  # O script da árvore
/public/stylesheets/tree.css # humm! o estilo.

Talvez o estilo da sua aplicações interfira diretamente no esboço da árvore.
Gnome Style é o default, para usar o Explorer Style descompacte img_tree_explorer.tar.gz em /public/images/tree
Instalação
Via svn
Adicione o repositório

script/plugin source svn://rubyforge.org/var/svn/railstree/vendor/plugins

Depois instale com

script/plugin install tree

Via local
Descompacte o arquivo railstree0.8.5.zip no diretório vendor/plugins do seu Rails. Entre no diretório tree e execute

ruby install.rb

O railstree funciona em conjunto com os scripts de ajax e javascripts default do rails, portando adicione na sua view o no seu layout os scripts

  &lt;%= javascript_include_tag 'prototype' %&gt;
  &lt;%= javascript_include_tag 'effects' %&gt;
  &lt;%= javascript_include_tag 'dragdrop' %&gt;
  &lt;%= javascript_include_tag 'controls' %&gt;

e depois o script e o css do railstree

  &lt;%= stylesheet_link_tag 'tree' %&gt;
  &lt;%= javascript_include_tag 'tree' %&gt;

ficando assim

  &lt;%= stylesheet_link_tag 'tree' %&gt;
  &lt;%= javascript_include_tag 'tree' %&gt;
  &lt;%= javascript_include_tag 'prototype' %&gt;
  &lt;%= javascript_include_tag 'effects' %&gt;
  &lt;%= javascript_include_tag 'dragdrop' %&gt;
  &lt;%= javascript_include_tag 'controls' %&gt;

Já tá pronto pra funcionar
Usando
A idéia é básica. Um nó pode ter filhos ou não. Para criar sua estrutura siga sempre a lógica de colocar um nó dentro do outro e um objeto da classe Tree para impressão dos dados na tela.
Exemplo:

a=Node.new(:label => 'A', :url => '/letras/a') # nome , link
b=Node.new(:label => 'B', :url => '/letras/b')
c=Node.new(:label => 'C', :url => '/letras/c')
d=Node.new(:label => 'D', :url => '/letras/d')
e=Node.new(:label => 'E', :url => '/letras/e')
f=Node.new(:label => 'F', :url => '/letras/f') # nó em filho
a &lt;&lt; b  #adicionando b em a
c &lt;&lt; a  #adicionando a em c
d &lt;&lt; e  #adicionando e em d

tree=Tree.new(:label => 'Root',:url=> '/letras/todas')
tree &lt;&lt; c  #Taca 'c' na raiz da tree
tree &lt;&lt; d  #Taca 'd' na raiz da tree
tree &lt;&lt; f  #Taca 'f'(sem filho) na raiz da tree

Podemos passar blocos para os nós. Exemplo da mesma estrutura acima, usando blocos


tree=Tree.new(:label => "Root",:url =>"/letras/todas") do |t|
    t << Node.new(:label => "C",:url =>"/letras/c") do |n|
      n << Node.new(:label => "A",:url =>"/letras/a") {|a| a << Node.new(:label => "B",:url =>"/letras/b")}
    end
 end

tree << Node.new(:label => "D",:url =>"/letras/d") {|d| d << Node.new(:label => "E",:url =>"/letras/E") }
tree << Node.new(:label => "F",:url =>"/letras/f")

E que Deus continue inspirando Yukihiro Matsumoto
Vc escolhe!
Tem mais uma, todo o node tem nodes e aceita um bloco(opcional)

a=Node.new("A","/letras/a")
 a.nodes do |n|
   #faça algo com os filhos
end

Personalizando…
Você poderá mudar os ícones de um nó fechado ou aberto, fazer referênciar pelo atributo href de uma âncora ou onclick para acessar uma função em javascript, falar para o nó aparecer aberto ou fechado, etc.

Mudando os ícones


a=Node.new(:label => "A",:url => "/letras/a")
a.icon='/images/db.png'
a.icon_open='/images/outroicone.png'

Exemplo, esse código


  tabelas1=%w(starttelephony startvoip customers  gateways)
  tabelas2=%w(teste1 teste2 ) 

  d1=Node.new(:label => "radius", :icon => "/images/data.png", :open => true)
  d2=Node.new(:label => "teste", :icon => "/images/data.png", :open => false)

  tabelas1.each do |t|
    no=Node.new(:label => t, :icon => "/images/table_sql.png")
    d1 << no
  end

  tabelas1.each do |t|
    no=Node.new(:label => t, :icon => "/images/table_sql.png")
    d1 << no
  end

  tabelas2.each do |t|
    no=Node.new(:label => t, :url => 'link aqui', :icon => "/images/table_sql.png")
    d2 << no
  end

  tr = Tree.new(:label => "Databases[solaris]")
  tr << d1
  tr << d2

Gera isto:
tree3.png

Falando para um node aparecer aberto ou fechado(se tiver filhos!)


# :open => true ou false, esse valor é passado para o javascript
a=Node.new(:label => "A",:url => "/letras/a", :open => true)
#ou
a.open=true

Link e eventos

Temos o atributo variável event_name que pode ser qualquer coisa que vc quer mais trabalha em conjunto com o atributo href, não obstante para criar um link teremos o seguinte:


Node.new(:label => "A",:url => "/letras/a")

é a mesma coisa de fazer isso


Node.new(:label => "A",:href => '/letra/a', :event_name => :href)

isso vai criar uma tag assim para o nó
<a href=’/letras/a’ > A </a>

Hummm!
Então para criar um nó que chama um javascript pode ser assim


Node.new(:label => "A", :url => "alert('nossa que doído!')", :event_name => :onclick )

#ou

a=Node.new
a.label="A"
a.url="alert('nossa que doído!')"
a.event_name= :onclick

Link for Rails
Tem um esquema legal, que é usar a mesmo mecanismo de link do Rails o link_to e o link_to_remote.
É necessário a adição da opção :base referenciando uma instância de qualquer controller para que o mecanismo interno do método url_for(rails) funcione adequadamente.

link_to

Node.new  :label => "Criar usuário",
          :link_to => {
            :base =&gt; @controller,
            :controller =&gt; "usuarios",
            :action =&gt; "adicionar" ,
            :id =&gt; 1
          }

assumindo que @controller é uma instância do controller, se tiver dentro de um controller troque @controller por self ficando :base => self.
Para um roteamento padrão do Rails isso é a mesmo coisa de


n=Node.new(:label => "Criar usuário",url => "/usuarios/adicionar/1")

Pode também fazer requisições em ajax utilizando a criação padrão do link_to_remote mais :base.

link_to_remote

Node.new  :label => "Adicionar usuário ",
          :link_to_remote => {
            :base =&gt; @controller,
            :controller =&gt; "usuarios",
            :update =&gt; "id_do_div",
            :url =&gt;{ :action =&gt; 'adicionar', :c=&gt; 'variavel C', :a =&gt; 'variavel A'}
          }
 }

Montando uma árvore de diretório
Vou demonstrar aqui gerando o path do RAILS_ROOT

 Tree.for(RAILS_ROOT)

Pronto. Isso gera
tree4.png

Extra Sintaxe

t=Tree.new(:label => 'Raiz')
t.child(:label => 'Pai').child(:label => 'filho').child(:label => 'espirito santo').child(:label => 'amem')

amem.png
ou para um filho


t.child(:label => 'Pai'){ |p| p.child(:label => 'filho') }
#ou
t.child Node.new(:label => 'Pai').child Node.new(:label => 'filho')

Para vários irmão


t.child Node.new(:label => 'a'),Node.new(:label => 'b'), Node.new(:label => 'c')

ou

t.mknodes(5) do |n,s|
      n.label="Link #{s}"
      n.url="/link/#{s}"
end

Obs.: Sugestão do Ronie Uliana

Obs2.: Criação dos nodes passando Hash foi sugestão do Marcelo Júnior

rghost - Plugin ou Gem?

Tuesday, July 10th, 2007

Você escolhe!!
rghost_plugin.png
Pra quem pediu, disponibilizei o rghost como plugin no repositório do rghost no RubyForge só descompactar no RAILS_ROOT/lib e reiniciar a aplicação.

Impressão direta via TCP/IP com RubyGhost

Tuesday, July 10th, 2007

Geralmente as impressoras de médio e grande porte disponibilizam uma porta TCP conhecida como ‘porta bruta’ de número 9100. Demonstrarei aqui uma forma de imprimir diretamente neste tipo de printer, para o nosso exemplo usaremos o driver postscript genérico da Adobe(PS-Adobe-3.0).
Models Contas e Clientes

class Contas < ActiveRecord::Base
  belongs_to :clientes
end
class Clientes < ActiveRecord::Base
  has_one :contas
end

Configurando as colunas

require 'rghost'
clientes=Clientes.find :all, :include => :contas, :limit => 10000

grid=DataGrid::RailsGrid.new :width => 4 , :align => :center
grid.col :codigo, :title => "Código do Cliente", :width => 5
grid.col :nome, :title => "Nome"
grid.col :created_on, :title => "Data de Cadastro ", :format => :eurodate
grid.col lambda { contas.login }, :title => "Login"
grid.data(clientes)

Criando o documento com dados do ActiveRecord

doc=Document.new :paper => :A4, :landscape => true, :duplex => true
doc.before_page_create do
  set Image.for("/tmp/fatura.eps")
end
doc.set grid
doc.done

Enviando o documento

printer = TCPSocket.open('192.168.1.70', 9100)
printer.write doc.render_stream(:ps)

Deve ter saído lá na impressora… :)

Para mais informações no RGhost - RubyForge . Documentação em português no RubyForge

Rghost v0.7 Encodings e proxy charset

Wednesday, June 13th, 2007

Com a versão 0.7 podemos agora usar diferentes codificação de fontes e conversão de charset de Ruby para Postscript.
Encodings disponíveis

  • AdobeExpert
  • AdobeLatinEncoding
  • Bengali
  • CodePage1250
  • CodePage1251
  • CodePage1252
  • CodePage1253
  • CodePage1254
  • CodePage1256
  • CodePage1257
  • CodePage1258
  • CodePage874
  • IsoLatin
  • MacCentralEuropean
  • MacCyrillice
  • MacGreek
  • MacHebrew
  • TeX-CorkEncoding
  • TeX-LGR-Greek
  • TeXMathExtensionEncoding
  • TeXMathItalicEncoding
  • TeXMathSymbolEncoding
  • TeX-T2AModified2Encoding
  • TeX-T2BAdobeEncoding
  • TeX-T2CAdobeEncoding
  • TeX-X2AdobeEncoding
  • TeX-XL2encoding
  • US-ASCII
  • UTF-8

Ideal para código fonte Ruby no mesmo formato dos dados do documento. Existem duas formas de setar o encoding da fonte:
Antes de usar o documento

RubyGhostConfig::GS[:font_encoding] = 'CodePage1252'

Na criação do documento

doc=Document.new :font_encoding => 'CodePage1252'

Agora quando o charset do código fonte está diferente dos dados é necessário a conversão dos formatos. Para este fim usamos um bloco retornando uma string antes da criação do documento.

Exemplo para código fonte no padrão UTF-8 com acentuação.

RubyGhostConfig::GS[:charset_convert]= lambda {|text| Iconv::iconv('latin1','utf8', text).to_s}

O gem e o manual da versão 0.7 disponível no RubyForge.

Console For The Web

Thursday, April 19th, 2007

Vou demonstrar ‘uma’ solução para utilização de recursos no estilo console como irb, bash, psql, gs e outros.
A estratégia é simples, vamos abrir um pipe com a aplicação e trocar mensagens.

Já vou dizendo, vou utilizar uma variável global, sem delongas se-pode-ou-não-pode se existe é por que pode usar, mas com cautela. Isso me fez lembra do goto do C, todo mundo condenava a utilização(até eu) mas o meu professor de Linguagens Formais e Compiladores (Rafael Corvinel) me tirou das trevas. Faziamos interpretadores de gramáticas em C utilizando funções e condicionais normalmente, ele disse “esse código funciona e está bem estruturado” vamos focar agora em desempenho… “vamos fazer com goto” é meu caro a coisa funfou mais rápido dos que a forma estruturada, portando não estou mais nas trevas nem no dogmatismo. Qual é o seu foco?

A classe ConsoleForWeb

class ConsoleForWeb

 attr_reader :output
 def initialize(pipe_name,open_now=false,mode="r+")
      @output=''
      @pipe_name=pipe_name
      @mode=mode
      open if open_now
  end
  def run(input)
      if @io
        @io.puts input.to_s
        @io.flush

      else
          raise Exception.new("Pipe is closed")
      end
  end

 def open
    unless @io
       @io=IO.popen(@pipe_name,@mode)
       @io.sync=false

       Thread.new do
           loop do
              @output << "<div>#{@io.readline.chomp}</div>"
           end
        end

    end
 end

 def close
   @io.close if id @io
 end
 def closed?
      @io.closed?
 end

end

No initialize é esperado o nome do pipe(executável do programa), se é para abrir o pipe durante a inicialização da instância e mode de abertura(para ler e escrever ‘r+’)

O método run executa o comando, output obtém o retorno(attr_reader) e open e close… não precisa falar.

View

Utilizei dois arquivos, o index.rhtml para criar a caixinha para ficar parecendo um console e o partial _console.rhtml que é o cara que vai renderizar as respostas dos nossos comandos. Veja.

index.rhtml

<%= stylesheet_link_tag 'scaffold' %>
<%= stylesheet_link_tag 'erails' %>
<%= javascript_include_tag "prototype" %>
<%= javascript_include_tag "controls" %>
<%= javascript_include_tag "effects" %>
<%= javascript_include_tag "erails" %>

<%= form_tag({:action=> "run",
              :controller => "testes"},
              :onload=>"posload();",
              :id=> 'irb',
              :onsubmit => "return false"
)%>
    <div class="console" id="console" onclick="posload();">
        <%= render :partial => "console" %>
    </div>
<%= end_form_tag %>

Observe que temos um javascript erails.js para enviar as informações em Ajax e atualizar o nosso console e um stylesheet chamado erails.css… o tema (disponíveis para download, lá em baixo)

_console.rhtml

 <%= @output.to_s %>
 >><input name="caixa" class="text" onkeypress="run(event,'irb');" type="text" id="caixa" />
 <script> posload(); </script>

Para cada requisição/resposta o _console.rhtml será chamado para renderizar a resposta e criar uma caixa de input.

Controller

Crie um controller chamado TestesController com duas ações, uma para index(cria o console) e a ação run que executa os comandos na classe ConsoleForWeb.

class TestesController < ApplicationController

  def index
    render :action => "index"
  end

  def run
    e=params[:caixa]
    $irb=ConsoleForWeb.new('irb --simple-prompt',true) unless $irb
    $irb.run(e.chomp) if e
    sleep 0.3
    @output=$irb.output.dup

    render :partial => "console"

end

Veja uma atribuição unica para a variável $irb portanto utilizaremos apenas uma variável global para armazenar a instância de ConsoleForWeb. Vamos brincar agora.

erails3.png

script/console

Vamos especializar a classe ConsoleForWeb para fazer proxy e verificação de comando, neste exemplo inibiremos os comandos exit, quit, kill e clear. Utilizaremos um console do rails

class IrbForWeb < ConsoleForWeb
  def initialize
    super('/local/projects/bossapp/script/console',true)
  end

  def run(cmd)
    case cmd
      when /^(exit|quit|kill)/:  @output << "han?\n"
      when /^(clear|\^C)/:  @output=""
      else
          super
      end
  end
end

off: Esse han? é em homenagem ao Solaris 2.4.3.
No controller o método run fica assim

   def run
       e=params[:caixa]
       $irb=IrbForWeb.new unless $irb
       $irb.run(e.chomp) if e
       sleep 0.3
       @output=$irb.output.dup

       render :partial => "console"

   end

Exemplo script/console
erails2.png
Onde colocar as classes ConsoleForWeb e IrbForWeb? Eu coloquei-as no mesmo arquivo do controller por ser um teste, coloque no lib ou em outro local que satisfaça suas necessidades.

É isso. Não é a melhor e nem a pior implementação … é “uma implementação”. Os arquivos estão aqui.