Posts Tagged ‘server’

Ruby on Rails plugin tableless_model

Postado em 11 ago 2009
Categoria(s) Plugins, Ruby on Rails

tableless_model

Ruby on Rails model sem banco de dados, com todo o poder do ActiveRecord e validações.

A principal utilidade é usar em formulários que não precisam de banco de dados, mas precisam das validações do ActiveRecord, form_for e rotas RESTful. Por exemplo formulário de contato.

Instalação

./script/plugin install git://github.com/patrickespake/tableless_model.git

Geradores

Gerador tableless_model

Cria o esboço de um novo tableless model. Passe o nome do tableless model, em CamelCased ou under_scored, e uma lista de pares de atributos opcionais como argumentos.

Os atributos pares opcionais são column_name:sql_type como argumentos, especificando os atributos do tableless model.

Você não tem que pensar em cada atributos lá na frente, mas ajuda a esboçar um pouco para que você possa começar a trabalhar com o tableless model imediatamente.

Isto gera uma classe tableless model em app/models, um teste de unidade em test/unit e uma fixture em test/fixtures/singular_name.yml

Exemplos:

./script/generate tableless_model contact

Cria o tableless model Contact, test e fixture:

  • Model: app/models/contact.rb
  • Test: test/unit/contact_test.rb
  • Fixtures: test/fixtures/contacts.yml
./script/generate tableless_model invite name:string body:text email:string

Cria o tableless model Invite com a string name, text body e string email.

Gerador tableless_scaffold

Tableless scaffolds é composto por vários recursos, a partir do model, controller e views, juntamente com um conjunto completo de testes. O recurso está pronto para ser usado como um ponto de partida, sendo RESTful, orientado para o pedido.

Passe o nome do tableless model (na forma singular), em CamelCased ou under_scored, como primeiro argumento, e uma lista de pares de atributos opcionais.

Os pares de atributos opcionais são column_name:sql_type, especificando os atributos do modelo.

Você não tem que pensar em cada atributo lá na frente, mas ajuda esboçar um pouco para que você possa começar a trabalhar com os recursos imediatamente.

Por exemplo ‘tableless_scaffold contact name:string telephone:string firm:string email:string message:text’ dá-lhe um tableless model com cinco atributos, um controlador para lidar com a criação, formulário para criar os contatos e routas declaradas em config/routes.rb.

Se você quiser remover todos os arquivos gerados, execute:

script/destroy scaffold ModelName

Exemplos:

./script/generate tableless_scaffold invite
./script/generate tableless_scaffold contact name:string telephone:string firm:string email:string message:text

Tipos de colunas disponíveis nos tableless_models

1
2
3
4
5
6
7
class ModelName < TablelessModel
  column :column_name1, :column_type
  column :column_name2, :column_type
  column :column_name3, :column_type
  column :column_nameN, :column_type
  ...
end

Tipos de colunas (column_type) disponíveis:

  • :string
  • :text
  • :integer
  • :float
  • :decimal
  • :datetime
  • :timestamp
  • :time
  • :date
  • :binary
  • :boolean

Validações do ActiveRecord funcionam perfeitamente

1
2
3
4
5
6
7
8
9
10
11
class Contact < TablelessModel
  column :name, :string
  column :telephone, :string
  column :firm, :string
  column :email, :string
  column :message, :text
 
  validates_presence_of :name, :email, :message
  validates_format_of :email, :with => /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i
  validates_length_of :message, :minimum => 3
end

Exemplo completo usando tableless_scaffold gerador

Criar o tableless scaffold

./script/generate tableless_scaffold contact name:string telephone:string firm:string email:string message:text

Adicionar as validações no model

Abra o arquivo app/models/contact.rb e adicione as validações:

1
2
3
4
5
6
7
8
9
10
11
12
class Contact < TablelessModel
  column :name, :string
  column :telephone, :string
  column :firm, :string
  column :email, :string
  column :message, :text
 
  # Validations
  validates_presence_of :name, :email, :message
  validates_format_of :email, :with => /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i
  validates_length_of :message, :minimum => 3
end

Execute

./script/server

Abra o seu navegador em: http://localhost:3000/contacts/new

Exemplo completo usando tableless_model gerador

Criar tableless model

./script/generate tableless_model contact name:string telephone:string firm:string email:string message:text

Adicionar as validações no model

Abra o arquivo app/models/contact.rb e adicione as validações:

1
2
3
4
5
6
7
8
9
10
11
12
class Contact < TablelessModel
  column :name, :string
  column :telephone, :string
  column :firm, :string
  column :email, :string
  column :message, :text
 
  # Validations
  validates_presence_of :name, :email, :message
  validates_format_of :email, :with => /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i
  validates_length_of :message, :minimum => 3
end

Criar o controlador

./script/generate controller contacts new create

Adicionar os códigos das actions:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class ContactController < ApplicationController
  def new
    @contact = Contact.new
  end
 
  def create
    @contact = Contact.new(params[:contact])
 
    if @contact.save # or @contact.valid?
      flash[:notice] = "Contact email sent successfully."
 
      # Send contact email
      #MyMailer.deliver_contact(@contact)
 
      redirect_to new_contact_path
    else
      render :action => "new"
    end
  end
end

Criar as routas para os contacts

Abra o arquivo config/routes.rb e adicione a linha:

1
2
3
4
ActionController::Routing::Routes.draw do |map|
  map.resources :contacts, :only => [:new, :create]
  ...
end

Criar o formulário de contato

Abra o arquivo app/views/contacts/new.html.erb e adicione o conteúdo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<% form_for(@contact) do |f| %>
  <%= f.error_messages %>
 
  <%= f.label :name %>
  <%= f.text_field :name %>
 
  <%= f.label :telephone %>
  <%= f.text_field :telephone %>
 
  <%= f.label :firm %>
  <%= f.text_field :firm %>
 
  <%= f.label :email %>
  <%= f.text_field :email %>
 
  <%= f.label :message %>
  <%= f.text_area :message %>
 
  <%= f.submit "Send" %>
<% end %>

Apague o arquivo app/views/contacts/create.html.erb.

Execute

./script/server

Abra o seu navegador em: http://localhost:3000/contacts/new

Documentação

http://lab.patrickespake.com/tableless_model

Código fonte

http://github.com/patrickespake/tableless_model

Se você gostou desse texto e acha que ajudou você, me recomende: Recommend Me.

  • Share/Bookmark

Ruby usando DRb (Distributed Ruby)

Postado em 18 jun 2009
Categoria(s) Ruby

DRb permite programas em Ruby se comunicar uns com os outros na mesma máquina ou através de uma rede, aplicação cliente/servidor. DRb utiliza o método de invocação remota (RMI) para transmitir comandos e dados entre os processos.

Nesse post vamos criar dois programas, o servidor e o cliente usando DRb.

Construíndo o servidor (server.rb):

1
2
3
4
5
6
7
8
9
10
11
require 'drb'
 
class Server
  def hello
    "Hello, This is a Distributed Ruby (DRb) Example"
  end
end
 
server_object = Server.new
DRb.start_service('druby://localhost:9000', server_object)
DRb.thread.join

Entendendo o código do servidor:

require 'drb'

A linha acima apenas requere a biblioteca DRb, essa biblioteca que a responsável por fazer a comunicação remota. Você pode encontrar mais informações a seu respeito em: http://www.ruby-doc.org/stdlib/libdoc/drb/rdoc/index.html.

class Server
  def hello
    "Hello, This is a Distributed Ruby (DRb) Example"
  end
end

O código acima apena cria uma classe e o método hello, que imprime uma mensagem.

server_object = Server.new
DRb.start_service('druby://localhost:9000', server_object)
DRb.thread.join

Essas três linhas acima que fazem o servidor funcionar, a primeira linha apenas faz a instância da classe Server, a segunda linha inicia o serviço remoto no endereço druby://localhost:9000 disponibilizando o objeto server_object, a terceira linha inicia uma thread no servidor para aceitar requisições remotas.

Construíndo o cliente (client.rb):

1
2
3
4
5
6
require 'drb'
 
DRb.start_service
obj = DRbObject.new(nil, 'druby://localhost:9000')
 
puts obj.hello

Entendendo o código do cliente:

require 'drb'

A linha acima apenas requere a biblioteca DRb, essa biblioteca que a responsável por fazer a comunicação remota. Você pode encontrar mais informações a seu respeito em: http://www.ruby-doc.org/stdlib/libdoc/drb/rdoc/index.html.

DRb.start_service
obj = DRbObject.new(nil, 'druby://localhost:9000')

As suas linhas acima inicia o serviço remoto com o servidor, a primeira inicializa o serviço e a segunda estabelece conexão com o servidor no endereço druby://localhost:9000 obtendo o objeto Server.

puts obj.hello

Essa linha acima invoca o método hello do objeto remoto Server.

Rodando o servidor:

Para inicializar o servidor digite na linha de comando:

ruby server.rb

Não será exibida nenhuma mensagem, o servidor apenas ficará esperando novas requisições remotas.

Rodando o cliente:

ruby client.rb

Quando você rodar o cliente terá como retorno a mensagem:

Hello, This is a Distributed Ruby (DRb) Example

Pronto! Esse recurso é muito interessante. ;-)

Se você gostou desse texto e acha que ajudou você, me recomende: Recommend Me.

  • Share/Bookmark

Ruby on Rails 2.2 como usar I18n, traduzir as mensagens de validação do model e atributos do model

Postado em 31 jan 2009
Categoria(s) Ruby on Rails

No Ruby on Rails 2.2 existe o suporte para I18n, ou seja, criar aplicações para múltiplos idiomas.

Vou mostrar como habilitar isso no Ruby on Rails 2.2.

Primeiro pare a sua aplicação.

Abra o arquivo environment.rb localizado no diretório config, nesse arquivo procure pela seguinte linha:

1
# config.i18n.default_locale = :de

Ela está comentada e até esse momento o idioma padrão do projeto e o inglês.

Remove o comentário dessa linha e defina o idioma padrão para “pt-BR”:

1
2
3
4
# The internationalization framework can be changed to have another default locale (standard is :en) or more load paths.
# All files from config/locales/*.rb,yml are added automatically.
# config.i18n.load_path << Dir[File.join(RAILS_ROOT, 'my', 'locales', '*.{rb,yml}')]
config.i18n.default_locale = "pt-BR"

Agora precisamos criar um arquivo chamado pt-BR.yml, nesse arquivo irá ficar as traduções dos termos do projeto para o português.

Crie o arquivo pt-BR.yml no diretório config/locales, esse diretório config/locales é responsável por armazenar todos os arquivos de tradução do projeto.

Adicione o seguinte conteúdo no arquivo pt-BR.yml:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
pt-BR:
  # formatos de data e hora
  date:
    formats:
      default: "%d/%m/%Y"
      short: "%d de %B"
      long: "%d de %B de %Y"
      only_day: "%d"
 
    day_names: [Domingo, Segunda, Terça, Quarta, Quinta, Sexta, Sábado]
    abbr_day_names: [Dom, Seg, Ter, Qua, Qui, Sex, Sáb]
    month_names: [~, Janeiro, Fevereiro, Março, Abril, Maio, Junho, Julho, Agosto, Setembro, Outubro, Novembro, Dezembro]
    abbr_month_names: [~, Jan, Fev, Mar, Abr, Mai, Jun, Jul, Ago, Set, Out, Nov, Dez]
    order: [:day,:month,:year]
 
  time:
    formats:
      default: "%A, %d de %B de %Y, %H:%M hs"
      time: "%H:%M hs"
      short: "%d/%m, %H:%M hs"
      long: "%A, %d de %B de %Y, %H:%M hs"
      only_second: "%S"
      datetime:
        formats:
          default: "%Y-%m-%dT%H:%M:%S%Z"
    am: ''
    pm: ''
 
  # date helper distanci em palavras
  datetime:
    distance_in_words:
      half_a_minute: 'meio minuto'
      less_than_x_seconds:
        one: 'menos de 1 segundo'
        other: 'menos de {{count}} segundos'
 
      x_seconds:
        one: '1 segundo'
        other: '{{count}} segundos'
 
      less_than_x_minutes:
        one: 'menos de um minuto'
        other: 'menos de {{count}} minutos'
 
      x_minutes:
        one: '1 minuto'
        other: '{{count}} minutos'
 
      about_x_hours:
        one: 'aproximadamente 1 hora'
        other: 'aproximadamente {{count}} horas'
 
      x_days:
        one: '1 dia'
        other: '{{count}} dias'
 
      about_x_months:
        one: 'aproximadamente 1 mês'
        other: 'aproximadamente {{count}} meses'
 
      x_months:
        one: '1 mês'
        other: '{{count}} meses'
 
      about_x_years:
        one: 'aproximadamente 1 ano'
        other: 'aproximadamente {{count}} anos'
 
      over_x_years:
        one: 'mais de 1 ano'
        other: 'mais de {{count}} anos'
 
  # numeros
  number:
    format:
      precision: 3
      separator: ','
      delimiter: '.'
    currency:
      format:
        unit: 'R$'
        precision: 2
        format: '%u %n'
        separator: ','
        delimiter: '.'
    percentage:
      format:
        delimiter: '.'
    precision:
      format:
        delimiter: '.'
    human:
      format:
        precision: 1
        delimiter: '.'
  support:
    array:
      sentence_connector: "e"
      skip_last_comma: true
 
  # Active Record
  activerecord:
    errors:
      template:
        header:
          one: "{{model}} não pôde ser salvo: 1 erro"
          other: "{{model}} não pôde ser salvo: {{count}} erros."
        body: "Por favor, cheque os seguintes campos:"
      messages:
        inclusion: "não está incluso na lista"
        exclusion: "não está disponível"
        invalid: "não é válido"
        confirmation: "não bate com a confirmação"
        accepted: "precisa ser aceito"
        empty: "não pode ser vazio"
        blank: "não pode ser vazio"
        too_long: "é muito longo (não mais do que {{count}} caracteres)"
        too_short: "é muito curto (não menos do que {{count}} caracteres)"
        wrong_length: "não é do tamanho correto (precisa ter {{count}} caracteres)"
        taken: "não está disponível"
        not_a_number: "não é um número"
        greater_than: "precisa ser maior do que {{count}}"
        greater_than_or_equal_to: "precisa ser maior ou igual a {{count}}"
        equal_to: "precisa ser igual a {{count}}"
        less_than: "precisa ser menor do que {{count}}"
        less_than_or_equal_to: "precisa ser menor ou igual a {{count}}"
        odd: "precisa ser ímpar"
        even: "precisa ser par"

Esse arquivo pt-BR.yml foi retirado de: http://github.com/svenfuchs/rails-i18n/tree/master nesse endereço você poderá encontrar traduções para outros idiomas.

Pronto! Agora é só rodar a aplicação e ver as mensagens e o restante traduzido para o português.

1
ruby script/server

Outro detalhe super importante e gera muitas perguntas nas listas e fóruns, é como traduzir os nomes dos atributos do model, por exemplo eu tenho um model com os seguintes atributos:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class CreateHistories < ActiveRecord::Migration
  def self.up
    create_table :histories do |t|
      t.string :title, :limit => 150, :null => false
      t.string :permalink, :limit => 255
      t.text :content, :null => false
      t.timestamps
    end
 
    add_index(:histories, :permalink, :unique => true)
  end
 
  def self.down
    drop_table :histories
  end
end

Eu tenho os atributos title, permalink e content, muitas pessoas como eu gostam de programar tudo em inglês.

O problema é quando é exibida as mensagens de validação, os nomes dos atributos vem todos em inglês, por exemplo:

1
2
3
4
5
6
2 erros para history
 
Foram detectados os seguintes erros:
 
    * Title não pode ser vazio
    * Content não pode ser vazio

Para resolver esse problema e ser feliz, existe um outro plugin chamado activerecord_i18n_defaults que pode ser encontrado aqui: http://github.com/dcrec1/activerecord_i18n_defaults/tree/master.

Vamos usar ele.

Instalação

No diretório raiz do projeto digite:

1
ruby script/plugin install git://github.com/dcrec1/activerecord_i18n_defaults.git

Agora lembra do arquivo pt-BR.yml que criamos acima, vamos abrir ele e inserir novas traduções para os atributos do model.

Procure no arquivo pt-BR.yml por essa parte:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
...
# Active Record
  activerecord:
    errors:
      template:
        header:
          one: "model não pôde ser salvo: 1 erro"
          other: "model não pôde ser salvo: count erros."
        body: "Por favor, cheque os seguintes campos:"
      messages:
        inclusion: "não está incluso na lista"
        exclusion: "não está disponível"
        invalid: "não é válido"
        confirmation: "não bate com a confirmação"
        accepted: "precisa ser aceito"
        empty: "não pode ser vazio"
        blank: "não pode ser vazio"
        too_long: "é muito longo (não mais do que count caracteres)"
        too_short: "é muito curto (não menos do que count caracteres)"
        wrong_length: "não é do tamanho correto (precisa ter count caracteres)"
        taken: "não está disponível"
        not_a_number: "não é um número"
        greater_than: "precisa ser maior do que count"
        greater_than_or_equal_to: "precisa ser maior ou igual a count"
        equal_to: "precisa ser igual a count"
        less_than: "precisa ser menor do que count"
        less_than_or_equal_to: "precisa ser menor ou igual a count"
        odd: "precisa ser ímpar"
        even: "precisa ser par"

Adicione o seguinte conteúdo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
...
  # Active Record
  activerecord:
    attributes:
      _all:
        created_at: "Data de criação"
        updated_at: "Data de atualização"
      history:
        title: "Título"
        content: "Conteúdo"
    errors:
      template:
        header:
          one: "model não pôde ser salvo: 1 erro"
          other: "model não pôde ser salvo: count erros."
        body: "Por favor, cheque os seguintes campos:"
      messages:
        inclusion: "não está incluso na lista"
        exclusion: "não está disponível"
        invalid: "não é válido"
        confirmation: "não bate com a confirmação"
        accepted: "precisa ser aceito"
        empty: "não pode ser vazio"
        blank: "não pode ser vazio"
        too_long: "é muito longo (não mais do que count caracteres)"
        too_short: "é muito curto (não menos do que count caracteres)"
        wrong_length: "não é do tamanho correto (precisa ter count caracteres)"
        taken: "não está disponível"
        not_a_number: "não é um número"
        greater_than: "precisa ser maior do que count"
        greater_than_or_equal_to: "precisa ser maior ou igual a count"
        equal_to: "precisa ser igual a count"
        less_than: "precisa ser menor do que count"
        less_than_or_equal_to: "precisa ser menor ou igual a count"
        odd: "precisa ser ímpar"
        even: "precisa ser par"

Ou seja, adicionei:

1
2
3
4
5
6
7
    attributes:
      _all:
        created_at: "Data de criação"
        updated_at: "Data de atualização"
      history:
        title: "Título"
        content: "Conteúdo"

Tudo que fica abaixo do atributo _all, no caso created_at e updated_at são atributos do model comuns entre vários models, você define ali e todo mundo que tiver esses atributos já serão traduzidos.

E a parte abaixo são atributos específicos do model history:

1
2
3
      history:
        title: "Título"
        content: "Conteúdo"

O bom de existir a parte com _all é que você não precisa ficar duplicando traduções, é o que as pessoas xaropes, manés e viciadas em acrónimos da informática chamam de DRY (o mundo seria bem melhor sem essas pessoas ;-)).

Eu percebi que a gem Brazilian Rails gera alguns conflitos nas mensagens de validações, por isso eu sugiro que você desabilite deixando o seu environment.rb assim:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
...
  # Specify gems that this application depends on.
  # They can then be installed with "rake gems:install" on new installations.
  # You have to specify the :lib option for libraries, where the Gem name (sqlite3-ruby) differs from the file itself (sqlite3)
  # config.gem "bj"
  # config.gem "hpricot", :version => '0.6', :source => "http://code.whytheluckystiff.net"
  # config.gem "sqlite3-ruby", :lib => "sqlite3"
  # config.gem "aws-s3", :lib => "aws/s3"
  # config.gem "brazilian-rails", :version => '2.0.13'
  config.gem "brcep", :version => '2.0.13'
  config.gem "brcpfcnpj", :version => '2.0.13'
  config.gem "brdata", :version => '2.0.13'
  config.gem "brdinheiro", :version => '2.0.13'
  config.gem "brhelper", :version => '2.0.13'
  config.gem "brnumeros", :version => '2.0.13'
  config.gem "brstring", :version => '2.0.13'
  # config.gem "brtraducao", :version => '2.0.13'
...

Mais informações: http://iain.nl/2008/09/translating-activerecord/.

Se você gostou desse texto e acha que ajudou você, me recomende: Recommend Me.

  • Share/Bookmark