set 20

Olá,

A Paz do Senhor primeiramente.

Escrevo este post por não encontrar um tutorial/artigo/blog que explique com detalhes este assunto.

Todos nós, desenvolvedores em ruby on Rails sabemos que existe GEM e PLUGIN, mas qual a diferença básica?

Gem – Quando instalada, fica disponível para qualquer projeto do ambiente onde está sendo executada as aplicações.

Plugin – Quando instalado, fica disponível somente para a aplicação em que foi instalado, por isso o comando deve ser executado dentro da pasta raiz do projeto.

Agora que já temos uma idéia melhor sobre o assunto, vamos instalar o brazilian-rails como gem. Execute o comando abaixo em qualquer lugar no terminal/console.

gem install brazilian-rails

Esse comando instala a gem e ficará disponível para todas as aplicações do ambiente/servidor em que estiver.

Para instalar como plugin, execute o comando abaixo, dentro da pasta da sua aplicação, na raiz:

ruby script/plugin install svn://rubyforge.org/var/svn/brazilian-rails

Uma outra coisa que dificilmente explicam é que quando você usa gem, você precisa ir no seu enviroment.rb e adicionar as linhas:

#brazilian-rails
require ‘brstring’
require ‘brdata’
require ‘brdinheiro’
require ‘brI18n’

… e outras que você precisar

Já quando você usa como plugin, você vai no enviroment e coloca as linhas:

Rails::Initializer.run do |config|
config.plugins = [:all]
config.i18n.default_locale = “pt-BR”
end

Ou seja, se usar gem você poe o require para sua aplicação saber que você está incluindo estes arquivos da gem e como plugin apenas diga que você quer usar todos os plugins da pasta de plugins.

Eu, Paulo, prefiro usar sempre como plugin, pois deixa a sua aplicação independente de servidor e não precisa ficar instalando gems.

Espero que tenham gostado :)

ago 4

Olá,

Hoje vos escrevo sobre algo básico, porém útil, mas que ninguém que trabalha com Rails soube me responder.

Trata-se da passagem de todos os campos do form direto para um objeto, mas tudo isso em 1 linha de código, Ohhhh!!

Esse código é gerado pelo scaffolding do Rails, mas fazendo o administrativo do site na mão (pois o scaffolding é básico e ninguém realmente usa isso) precisei disso, de passar tudo direto para o objeto sem precisar escrever atributo por atributo, então segue ai um exemplo da estrutura que os campos do form precisam ter para analisar-mos.

<input name=”id” value=”150″ type=”hidden” />

<input name=”dados[nome]” value=”teste” type=”text” maxlenght=”50″ />

<input name=”dados[ativo]” value=”1″ type=”checkbox” />

Vamos supor que tenhamos uma classe chamada Cliente que possui os atributos:

nome [varchar: 50]

ativo [tinyint: 1]

Para jogar-mos esses dois atributos para uma instância da classe Cliente e gravar no banco precisamos fazer assim no Rails:

cliente = Cliente.new(params[:dados])

cliente.save

e para alterar os atributos de um Cliente já existente, usamos:

cliente = Cliente.find(params[:id])

cliente.update_attributes(params[:dados])

#não precisa do cliente.save, pois o método update_attributes já faz isso por você

Agora, a explicação é bem simples, quando você cria um array de campos e cada campo tem o nome de um atributo da classe final, quando você passar este array por parâmetro o Ruby on Rails vai verificar e jogar automaticamente os campos do form para cada atributo do objeto.

Então se tempo no form um campo chamado dados[nome] e em nome classe temos o atributo nome, na passagem dos dados automaticamente o atributo nome recebe o valor do campo dados[nome].

Pelo scaffold, ele cria os forms contendo o nome do array sendo o nome da classe, então se você gerar um scaffold para cliente, ele vai gerar os nomes dos campos assim:  cliente[nome], cliente[ativo].

Mas isso pouco importa, pois o nome do array não muda em nada, apenas trocariamos de:

Cliente.new(params[:dados])

para

Cliente.new(params[:cliente])

Para economizar trabalho, eu sempre crio os forms com os mesmos nomes de campos, assim quando vou criar um form igual apenas copio as mesmas views e está tudo certo, sei que o nome do array sempre será dados, mas isso é de cada um, o importante é entender o funcionamento.

Espero que tenham gostado, pois isso é algo que dificilmente você encontrará explicando por ai, eu mesmo não achei, só testando o scaffold mesmo para notar isso.

—————————————————————————————-

Estou editando o post pois um amigo (Marcus Vinicus) da lista rails-br me alertou sobre uma forma de hackearem sua aplicação através desta facilidade chamada mass-assignment que foi explicada acima.

Vou tentar explicar o funcionamento de como alguém pode burlar uma aplicação usando o mass-assignment e como podemos nos proteger facilmente com o Rails.

Bom, como expliquei, os valores dos campos são passados diretamente para o objeto, mas nós só colocamos em nosso form os campos nome e ativo, e se tivessemos um atributo em nossa classe chamado admin, ficando assim nossa estrutura:

nome [varchar: 50]

ativo [tinyint: 1]

admin [tinyint: 1]

Sendo que em nosso form só temos 2 campos e este campo admin nós não usamos ele no cadastro do registro nem na alteração, pois somente um usuário é admin e este usuário é um registro qualquer do nosso banco de dados que tem direito a fazer tudo na aplicação, então não precisamos disponibilizar em nosso form esse campo para informar se o usuário é admin ou não, já que decidimos que em nossa aplicação só tem 1 admin e ele já está lá com o valor 1 neste campo da tabela.

Mas ai, vamos supor que um engraçadinho, usando o Firebug do Firefox editou o html e adicionou em nosso form que antes era:

<input name=”dados[nome]” value=”teste” type=”text” maxlenght=”50″ />

<input name=”dados[ativo]” value=”1″ type=”checkbox” />

e mudou para:

<input name=”dados[nome]” value=”teste” type=”text” maxlenght=”50″ />

<input name=”dados[ativo]” value=”1″ type=”checkbox” />

<input name=”dados[admin]” value=”1″ type=”text” />

E quando ele fez o submit no form, o Rails jogou tudo pro objeto Cliente, inclusive o valor do campo admin, e com isso atribuiu para o objeto Cliente o valor 1 para o atributo admin, fazendo com que aquele usuário seja também um administrador do sistema e tenha acesso a tudo.

Obviamente, o Rails sempre tem seus métodos de proteção, e agora vou explicar como permitir somente que alguns campos sejam definidos pelo mass-assignment.

Para fazer essa façanha super difícil, basta na sua classe você especificar assim (com base em nossa classe Cliente):

class Cliente < ActiveRecord::Base
attr_accessible :nome, :ativo
end

Com isso, estamos dizendo que em nossa classe Cliente, somente nos atributos nome e ativo é permitido usar o mass-assignment ou também podemos proibir os campos que não queremos que o mass-assignment atribua valores, assim:

class Cliente < ActiveRecord::Base
attr_protected :admin
end

Assim, estamos definindo em nossa classe Cliente que o campo admin está protegido e que não se pode usar o mass-assignment nele.

Bem simples né? Como tudo no Rails.

Obrigado ao Marcus pela dica do mass-assignment.

ago 2

Olá,

Assim como pregamos o que vivemos, eu também escrevo o que vivo no dia-a-dia e aprendo com as pessoas.

Então, a partir de uma necessidade de um amigo, pesquisei como seria para escrever um arquivo de texto simples, um TXT da vida, com o Ruby on Rails, na verdade só com o Ruby, e encontrei uma solução:

nome_arquivo = RAILS_ROOT + ‘/pasta/arquivo.txt’

arquivo = File.open(nome_arquivo, ‘wb’)
arquivo.puts “nome: Paulo”
arquivo.close

Caso você queira enviar este arquivo para download, existe o comando send_file que faz isto para você, assim:

#seguindo o exemplo acima

send_file nome_arquivo

Mas informações sobre o send_file:

http://api.rubyonrails.org/classes/ActionController/Streaming.html

Mas informações sobre a classe File:

http://corelib.rubyonrails.org/classes/File.html

jun 7

Olá,

Descoberta uma falha na autenticação no rails.

Link: http://n8.tumblr.com/post/117477059/security-hole-found-in-rails-2-3s

mai 7

Olá,

Vou postar hoje uma solução para mais uma necessidade que tive, eu precisava fazer no rails com que fosse ignorado o nome que ele sugere para a tabela um modelo específico, mas como fazer isso de maneira rápida sem precisar alterar todo um mundo de coisas?

Eis a solução:

No seu modelo coloque:

class AnuncioServico < ActiveRecord::Base
  def self.table_name() "anuncios_servicos" end
end

O que importa na verdade é a linha do meio em negrito, onde ali você define o nome da tabela que você quer.

Abraços e fiquem com Deus.

EDITADO EM 07/09/2009

Seguindo a dica do amigo Mereghost também é possível fazer de uma forma simplificada ficando assim:

class AnuncioServicoServico < ActiveRecord::Base
  set_table_name 'anuncios_servicos_servicos'
end

Com certeza fica bem melhor, obrigado pela ajuda.

Fiquem na paz de Deus.