Posts Tagged ‘html’

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 on Rails usando strip_tags nos controllers, models e libs

Postado em 15 jun 2009
Categoria(s) Ruby on Rails

O Ruby on Rails possui o métogo strip_tags para remover tags html. Esse método está apenas disponível na camada de view, uma vez que faz parte ActionView::Helpers::SanitizeHelper.

Eu não concordo com essa implementação do Rails, acho que deveria ser disponível também na camada de controller e model, onde são os lugares que esse método é mais útil.

Para implementar o strip_tags nos controllers, models e libs, nós podemos adicionar esse método na classe String, desta forma estará disponível em qualquer lugar.

Abra o arquivo config/initializers/new_rails_defaults.rb:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# Be sure to restart your server when you modify this file.
 
# These settings change the behavior of Rails 2 apps and will be defaults
# for Rails 3. You can remove this initializer when Rails 3 is released.
 
if defined?(ActiveRecord)
  # Include Active Record class name as root for JSON serialized output.
  ActiveRecord::Base.include_root_in_json = true
 
  # Store the full class name (including module namespace) in STI type column.
  ActiveRecord::Base.store_full_sti_class = true
end
 
# Use ISO 8601 format for JSON serialized times and dates.
ActiveSupport.use_standard_json_time_format = true
 
# Don't escape HTML entities in JSON, leave that for the #json_escape helper.
# if you're including raw json in an HTML page.
ActiveSupport.escape_html_entities_in_json = false

Adicione no final do arquivo as linhas:

1
2
3
4
5
class String
  def strip_tags
    ActionController::Base.helpers.strip_tags(self)
  end
end

As linhas acima criam o método strip_tags na classe String.

Ficando o arquivo completo assim:

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
# Be sure to restart your server when you modify this file.
 
# These settings change the behavior of Rails 2 apps and will be defaults
# for Rails 3. You can remove this initializer when Rails 3 is released.
 
if defined?(ActiveRecord)
  # Include Active Record class name as root for JSON serialized output.
  ActiveRecord::Base.include_root_in_json = true
 
  # Store the full class name (including module namespace) in STI type column.
  ActiveRecord::Base.store_full_sti_class = true
end
 
# Use ISO 8601 format for JSON serialized times and dates.
ActiveSupport.use_standard_json_time_format = true
 
# Don't escape HTML entities in JSON, leave that for the #json_escape helper.
# if you're including raw json in an HTML page.
ActiveSupport.escape_html_entities_in_json = false
 
class String
  def strip_tags
    ActionController::Base.helpers.strip_tags(self)
  end
end

Agora reinicie o seu servidor web para pegar essas novas configurações na inicialização da aplicação.

Agora quando você precisar do strip_tags pode usar assim, exemplos:

params['title'] = params['title'].strip_tags
 
ou
 
>> '<b>meu texto</b>'.strip_tags
=> "meu texto"

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

  • Share/Bookmark

Ruby on Rails usando o helper Cycle de uma forma mais apurada

Postado em 09 jun 2009
Categoria(s) Ruby on Rails

O helper cycle é legal para trabalhar com alternância de classes css em linhas de uma tabela, divs, listas e outros elementos html. Quando você deseja que as linhas pares fiquem de uma cor e as linhas ímpares fiquem de outra cor.

Por exemplo:

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
<table class="media-table">
  <caption>Photos</caption>
 
  <thead>
    <tr>
      <th class="photo">Photo</th>
      <th class="description">Description</th>
      <th class="actions">Actions</th>
    </tr>
  </thead>
 
  <tbody>
    <% if @message.photos.size > 0%>
      <% for photo in @message.photos %>
        <tr class="<%= cycle('even', 'odd') %>">
          <td><%= image_tag photo.file.url(:thumb) %></td>
          <td><%= photo.description %></td>
          <td class="actions">
            <%= link_to_delete message_photo_path(@message, photo) %>
          </td>
        </tr>
      <% end %>
    <% else %>
      <tr>
        <td colspan="3">No photos.</td>
      </tr>
    <% end %>
  </tbody>
</table>

E você pode ter uma regra css da seguinte forma:

1
2
3
4
5
6
table.media-table tr.even {
}
 
table.media-table tr.odd {
  background-color: #e5eefa;
}

Desta forma todas as linhas ímpares ficaram de uma cor diferente.

É um helper bem simples que permite deixar suas tabelas, divs, listas e outros itens htmls bem legíveis através de regras css adequadas.

Você pode encontrar um problema de estilização quando usar o helper cycle em duas tabelas distintas conforme exemplo:

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
<table class="media-table">
  <caption>Photos</caption>
 
  <thead>
    <tr>
      <th class="photo">Photo</th>
      <th class="description">Description</th>
      <th class="actions">Actions</th>
    </tr>
  </thead>
 
  <tbody>
    <% if @message.photos.size > 0%>
      <% for photo in @message.photos %>
        <tr class="<%= cycle('even', 'odd') %>">
          <td>< %= image_tag photo.file.url(:thumb) %></td>
          <td>< %= photo.description %></td>
          <td class="actions">
            <%= link_to_delete message_photo_path(@message, photo) %>
          </td>
        </tr>
      <% end %>
    <% else %>
      <tr>
        <td colspan="3">No photos.</td>
      </tr>
    <% end %>
  </tbody>
</table>
 
<br />
<br />
 
<table class="media-table">
  <caption>Videos</caption>
 
  <thead>
    <tr>
      <th class="video">Video</th>
      <th class="description">Description</th>
      <th class="actions">Actions</th>
    </tr>
  </thead>
 
  <tbody>
    <% if @message.videos.size > 0 %>
      <% for video in @message.videos %>
        <tr class="<%= cycle('even', 'odd') %>">
          <td><%= video.file.url %></td>
          <td><%= video.description %></td>
          <td><%= link_to_delete message_video_path(@message, video) %></td>
        </tr>
      <% end %>
    <% else %>
      <tr>
        <td colspan="3">No videos.</td>
      </tr>
    <% end %>
  </tbody>
</table>

No exemplo acima nós temos duas tabelas, uma para as fotos e outra para os vídeos. Nessa situação pode acontecer da próxima linha da tabela de vídeos ser pintada com a regra css odd, caso o número de linhas da tabela de fotos seja par.

Isso acontece por que o helper cycle não zera o seu contador entre um uso e outro.

Para trabalhar adequadamente você pode dar um nome para cada uso do helper cycle, desta forma:

1
2
3
4
5
...
<%= cycle('even', 'odd', 'row_photos') %>
...
<%= cycle('even', 'odd', 'row_videos') %>
...

Fazendo isso cada uso do helper cycle terá o seu próprio contador, e o problema de pintar o cabeçalho da tabela não ocorre mais.

Existe uma outra opção, você pode usar o helper cycle como mencionado no primeiro exemplo, sem definir um nome para cada uso do helper cycle, entre um uso e outro do helper cycle você pode pedir para zerar o seu contador, chamando o helper reset_cycle, exemplo:

1
2
3
4
5
6
7
...
<%= cycle('even', 'odd') %>
...
<% reset_cycle %>
...
<%= cycle('even', 'odd') %>
...

O helper reset_cycle também aceita zerar apenas um determinado helper cycle, basta informar o nome que você deseja zerar:

1
<% reset_cycle("row_photos") %>

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

  • Share/Bookmark

Criando menu drop down em javascript usando o framework Prototype

Postado em 16 jan 2009
Categoria(s) JavaScript, Prototype

Hoje eu precisei construir um menu drop down em javascript. Procurei na internet vários tipos de menus, encontrei alguns que só funcionavam com ul e li, outros eram complexos demais e na verdade o que eu queria e colocar o mouse em cima de um link e fazer aparecer um div com os itens do menu :-). Acabei decidindo por implementar o meu próprio sistema de menu com a ajuda desse artigo: http://javascript-array.com/scripts/simple_drop_down_menu/.

Para fazer o menu eu usei o framework JavaScript Prototype (http://www.prototypejs.org/).

Mãos a obra!

Carregue na página o framework Prototype:

1
<script src="/javascripts/prototype.js" type="text/javascript"></script>

Eu montei o menu e submenu com a seguinte estrutura HTML:

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
<!-- begin: menu -->
<div id="menu">
<ul>
	<li class="item1" id="menu1"><a href="#">INFORMA&Ccedil;&Atilde;O</a></li>
	<li class="item2" id="menu2"><a href="#">CAPACITA&Ccedil;&Atilde;O E APERFEI&Ccedil;OAMENTO</a></li>
	<li class="item3" id="menu3"><a href="#">EDITORA</a></li>
</ul>
</div>
<!-- end: menu -->
 
<!-- begin: submenu -->
<div id="submenu">
  <!-- begin: submenu 1 -->
<div id="submenu1" class="submenu" style="display:none;">
<ul class="column1">
	<li><a href="#" class="item111">Institucional</a></li>
	<li><a href="#" class="item112">Produtos</a></li>
	<li><a href="#" class="item113">Trabalhe Conosco</a></li>
	<li><a href="#" class="item114">Receba nosso news</a></li>
	<li><a href="#" class="item115">Contato</a></li>
</ul>
<ul class="column2">
	<li><a href="#">Podcasts</a></li>
	<li><a href="#">RSS</a></li>
	<li><a href="#">E-commerce</a></li>
	<li><a href="#">TV</a></li>
	<li><a href="#">Vantagens</a></li>
</ul>
<ul class="column3">
	<li><a href="#" class="item131">Artigos</a></li>
	<li><a href="#" class="item132">Calend&aacute;rio de Cursos</a></li>
</ul>
</div>
<!-- end: submenu 1 -->
  <!-- begin: submenu 2 -->
<div id="submenu2" class="submenu" style="display:none;">
<ul class="column1">
	<li><a href="#" class="item211">Institucional</a></li>
	<li><a href="#" class="item212">Produtos</a></li>
	<li><a href="#" class="item213">Trabalhe Conosco</a></li>
	<li><a href="#" class="item214">Receba nosso news</a></li>
	<li><a href="#" class="item215">Contato</a></li>
</ul>
<ul class="column2">
	<li><a href="#">Podcasts</a></li>
	<li><a href="#">RSS</a></li>
	<li><a href="#">E-commerce</a></li>
	<li><a href="#">TV</a></li>
	<li><a href="#">Vantagens</a></li>
</ul>
<ul class="column3">
	<li><a href="#" class="item231">Artigos</a></li>
	<li><a href="#" class="item232">Calend&aacute;rio de Cursos</a></li>
</ul>
</div>
<!-- end: submenu 2 -->
  <!-- begin: submenu 3 -->
<div id="submenu3" class="submenu" style="display:none;">
<ul class="column1">
	<li><a href="#" class="item311">Institucional</a></li>
	<li><a href="#" class="item312">Produtos</a></li>
	<li><a href="#" class="item313">Trabalhe Conosco</a></li>
	<li><a href="#" class="item314">Receba nosso news</a></li>
	<li><a href="#" class="item315">Contato</a></li>
</ul>
<ul class="column2">
	<li><a href="#">Podcasts</a></li>
	<li><a href="#">RSS</a></li>
	<li><a href="#">E-commerce</a></li>
	<li><a href="#">TV</a></li>
	<li><a href="#">Vantagens</a></li>
</ul>
<ul class="column3">
	<li><a href="#" class="item331">Artigos</a></li>
	<li><a href="#" class="item332">Calend&aacute;rio de Cursos</a></li>
</ul>
</div>
<!-- end: submenu 3 --></div>
<!-- end: submenu -->

Implementei o seguinte JavaScript que faz o menu drop down funcionar:

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
Event.observe(window, 'load', initMenuSystem);
 
var timeout = 500;
var closetimer = 0;
var ddmenuitem = 0;
 
function initMenuSystem() {
  configMenuItem('menu1', 'submenu1');
  configMenuItem('menu2', 'submenu2');
  configMenuItem('menu3', 'submenu3');
}
 
function configMenuItem(menu, submenu) {
  $(menu).observe('mouseover', function() {
    mopen(submenu)
  });
 
  $(menu).observe('mouseout', function() {
    mclosetime();
  });
 
  $(submenu).observe('mouseover', function() {
    mcancelclosetime();
  });
 
  $(submenu).observe('mouseout', function() {
    mclosetime();
  });
}
 
function mopen(id) {
  mcancelclosetime();
 
  if (ddmenuitem) {
    ddmenuitem.hide();
  }
 
  ddmenuitem = $(id);
  ddmenuitem.show();
}
 
function mclosetime() {
  closetimer = window.setTimeout(mclose, timeout);
}
 
function mclose() {
  if (ddmenuitem) {
    ddmenuitem.hide();
  }
}
 
function mcancelclosetime() {
  if (closetimer) {
    window.clearTimeout(closetimer);
    closetimer = null;
  }
}

Pronto! Ufaaa!

  • Share/Bookmark