overview.pt_BR 15.4 KB
= Menu

* MVC
* Como criar um Article? 
* Como criar um Block?
* Como criar uma Task?
* Visão Geral do Banco de Dados

= MVC

A sigla MVC vem de Modelo, Visão e Controle. Esta arquitetura sugere uma separação do código em três camadas distintas, com papéis bem definidos. 

A Visão é a camada que interage diretamente com o usuário, recebendo e disponibilizando os dados da aplicação. A camada de Visão tem o objetivo de apresentar o resultado do processamento da camada de Controle, formatada para ser usável pelo usuário, consituindo a parte visível do sistema.

A camada de Controle é a responsável por processar todas as requisições feitas pelo usuário através da interface (Visão). Esta camada interpreta as ações do usuário e gerencia a execução das regras de negócios pelo Modelo.

O modelo refere-se ao gerenciamento da informação e ao comportamento da aplicação. Em uma visão simplificada, a camada de modelo funciona como uma representação das entidades de domínio e suas regras de negócio. Possui a função de validar os dados vindos da interface do usuário com os dados da aplicação.

= Como criar um Article? 

Um artigo é um tipo de conteúdo que um usuário pode criar e gerenciar através do botão "gerenciar conteúdo" no seu painel de controle. Ele também é listado no bloco "conteúdo recente" e em alguns outros lugares como no resultado das buscas por exemplo. Os artigos podem ser de vários tipos, artigos que usam marcação de texto textile é um tipo de artigo, artigos com edição visual WYSIWYG é um outro tipo, artigos também podem ser arquivos enviados pelo usuário ou um simplesmente um feed RSS.

Cada um desses tipos de artigo são subclasses de Article que implementam métodos para editá-lo e exibi-lo. Os métodos que tem que ser sobrescritos são: to_html (para converter o conteudo em html), decription e short_decription (para indicar o que o artigo é para um usuário). Para cada Model que representa um tipo especifico de Article deve existir também um partial rhtml na pasta de views do controller cms em app/views/cms com o nome do tipo de artigo que é a interface de edição do artigo.

Então basicamente o layout de um novo tipo de artigo ficaria assim:

class NovoTipo < Article
  def description
    _('Este é um novo tipo de artigo')
  end
  def short_description
    _('Novo tipo de artigo')
  end
  def to_html
    #Algum código para gerar o html a partir de outras informações armazenadas
  end
end

Por padrão já existem alguns atributos que podem ser usados na geração do html para o artigo.

* body       - corpo do artigo
* name       - nome do artigo
* created_at - quando o artigo foi criado
* updated_at - quando foi alterado pela última vez

Caso seja necessário armazenar alguma informação além destas pode-se adicionar campos personalizados com o método setting_items.

Para criar por exemplo um artigo que mostre um texto com uma lista de referêcias em separado pode-se adicionar um campo de texto usando settings_items para armazenar as referências.

app/model/texto_com_referencia.rb

class TextoComReferencia < Article
  def description
    _('Este é uma artigo com referências em separado.')
  end
  def short_description
    _('Artigo com referêcias')
  end
  settings_items :referencias, :type => 'text'
  def to_html
    body + "<div>#{referencias}</div>"
  end
end

Então o html gerado iria adicionar ao fim do artigo as referêcias dentro de um div.

Para a edição do nosso artigo criamos o partial em app/views/cms/_texto_com_referencia.rhtml contendo:

<%= f.text_field('name') %>
<%= f.text_area('body') %>
<%= f.text_area('referencias') %>

Que gera uma formulário html para que o usuário do artigo digite o nome do artigo, o texto principal e as referências

= Como criar um Block?

Um block no Noosfero é uma caixa de conteúdo que pode ser escolhida para ser mostrada na página de um usuário/comunidade/empreendimento. Existem blocks para várias funcionalidades distintas como listar links favoritos, listar amigos, mostrar informações do usuário entre outros.

Um novo block é um model que herda da classe Block e tem que implementar os seguintes métodos:

* description       - retorna uma string que é a descrição do bloco (este é um método de classe)
* short_description - retorna uma string que é uma descrição curta do bloco (esse é um método de classe)
* default_title     - é o título padrão do bloco que pode ser mudado pelo usuário depois
* help              - um texto de ajuda que aparece quando o usuário entra no modo ajuda e passa o mouse por cima do bloco
* content           - retorna o conteúdo a ser exibido dentro do bloco

O método content pode retornar uma de duas coisas: uma string com o conteúdo que deve ser exibido ou uma função lambda com código que deve ser executado no contexto da requisição. A função lambda é útil para o caso de se querer utilizar um arquivo rhtml para gerar o html em vez de colocar tudo em uma string.

Se queremos, por exemplo, criar um bloco que mostra apenas as amigas de um usuário podemos usar o seguinte:

class Amigas < Block
 def self.description
   _('Um bloco que mostra o nome de suas amigas')
 end
 def self.short_description
   _('Bloco de amigas')
 end
 def default_title
   _('Minhas amigas')
 end
 def help
   _('Um bloco que mostra minhas amigas')
 end
 def content
   '<ul>' +
   owner.friends.select {|f|f.sex == 'female'}.map do |friend|
     '<li>' + friend.name + '</li>'
   end + 
   </ul>
 end
end

Depois disso é só adicionar o bloco na lista de blocos disponíveis aos usuários no controller app/controller/my_profile/profile_design_controller.rb. Se o bloco é para ser usado somente para usuários ou somente para comunidades deve ser adicionado em sua própria seção.

= Como criar uma Task?

Uma Task é um elemento do Noosfero utilizado para gerenciar tarefas pendentes. Essas tarefas são mostradas no painel de controle do usuário/comunidade/empreendimento que deve resolvê-la. Cada tarefa pode estar em 3 estados diferentes: pendente, resolvida ou cancelada. 

A classe Task provê a infra-estrutura básica para todas as tasks do sistema, o Noosfero hoje possui tasks para as seguintes funções: adicionar amigo, entrar em comunidade moderada, alteração de senha, entre outras. Esta classe contém relacionamento com Person e Profile da seguinte forma:
    _________            ______             ________
   |         |          |      |           |        |
   | Profile |1--------*| Task |*---------1| Person |
   |_________|          |______|           |________|

A classe base Task possui toda a lógica necessária para a existencia de tasks como o estado da tarefa, métodos para criação e finalização, envio de notificação, envio de email caso necessário, entre outras funções. Então o que resta para as classes derivadas é implementar o método perform que fará o trabalho propriamente dito, e adicionar campos personalizados caso necessário.

A task AddFriend por exemplo, que é uma task criada quando alguem requisita a amizade de outra pessoa, executa os seguintes passos no método perform ao ser finalizada.

* Adiciona requisitante como amigo do requisitado e;
* Adiciona requisitado como amigo do requitante

Para que o ciclo de criação, aceitação e finalização de uma task esteja completo é necessário implementar os controllers e as views. Para o AddFriend por exemplo temos o controller friends_controller que contém a lógica de criação da task. Para processamento desta e de todas as outras tasks temos o controller tasks_controller que contém a lógica necessária para finalizar uma task. Em views/tasks/ temos diversas views necessárias para a finalização de tasks, algumas tasks não necessitam campos especificos na sua finalização então usam a view _task.rhtml para a task AddFriend por exemplo temos o campo groups_for_friend usado para classificar um amigo no momento da aceitção da task.

No exemplo de código abaixo vamos criar uma Task AddFriend onde o Person joão requisita amizade do Person josé:

* joao = Person['joao']
* jose = Person['jose']
* AddFriend.create(:person => joao, :friend => jose)

José receberá uma requisição para ser amigo de joão, se ele aceitar a requisição o método perform será executado e o relacionamento de amizade entre eles será criado.

Vamos exemplificar como criar uma nova Task que simplesmente envia uma requisição para alguém e ao ser finalizada cria um artigo para quem aceitou a requisição.

Vamos chamar esta task de SendArticle, para isto crie o arquivo app/models/send_article.rb com o seguinte conteudo:

class SendArticle < Task
  validates_presence_of :requestor_id, :target_id
  acts_as_having_settings :name, :body, :field => :data
  def perform
    target.articles << TextileArticle.new(:name => name, :body => body)
  end
  def description
    _('%s enviou um artigo para você') % requestor.name
  end
end

Esta é a infra-estrutura para nossa nova task, uma classe que herda de Task e implementa pelo menos o método perform. Este task possui 2 campos personalizados que serão utilizados para armazenar o nome e o corpo do artigo a ser criado.

Para que seja possivel um usuario qualquer do sistema possa criar uma task dessa temos que implementar a lógica no controller e adicionar um botão na interface ou outro controle qualquer que possibilite o usuario criar, para isto vamos criar um controller.

app/controllers/public/send_article_controller.rb

class SendArticleController < MyProfileController
  def new
    @person = Person.find(params[:target_id])
    @article = TextileArticle.new
    if request.post? && params[:confirmation]
      SendArticle.create!(:requestor_id => user.id, :target_id => @person.id)
      flash[:notice] = _('%s receberá solicitação de criação deste artigo.') % @person.name
      redirect_to :back
    end
  end
end

Cria uma view com o form para que o usuario possa preencher o nome e o corpo do artigo a ser enviado ao criar a task.

app/views/send_article.rhtml

<h1><%= _('Sending article to %s') % @person.name %></h1>
<% labelled_form_for 'article', @article, :html => { :multipart => true } do |f| %>
  <%= hidden_field_tag(:confirmation, 1) %>
  <%= hidden_field_tag(:target_id, @person.id) %>
  <%= render :partial => 'cms/textile_article', :locals => { :f => f } %>
  <% button_bar do %>
    <%= submit_button :save, _('Send') %>
    <%= button(:cancel, _("Cancel"), :controller => 'profile', :profile => profile.identifier) %>
  <% end %>
<% end %>

Falta apenas adicionar um controle na interface para o usuário acionar este ação, vamos adicionar um botão junto aos botões de acão como adicionar amigo, entrar em comunidade, etc. em app/views/blocks/profile_info_actions/person.rhtml adicione o código abaixo.

<li> <%= link_to content_tag('span', _('Send article')), {:profile => user.identifier, :controller => 'send_article', :action => 'new', :target_id => profile.id}, :class => 'button with-text icon-menu-mail' %> </li>

= Visão Geral do Banco de Dados

O Noosfero é composto por 27 tabelas, listadas abaixo:

  +--------------------------------+
  | Tables_in_noosfero_development |
  +--------------------------------+
  | article_versions               | 
  | articles                       | 
  | articles_categories            | 
  | blocks                         | 
  | boxes                          | 
  | categories                     | 
  | categories_profiles            | 
  | comments                       | 
  | consumptions                   | 
  | domains                        | 
  | environments                   | 
  | favorite_enteprises_people     | 
  | friendships                    | 
  | images                         | 
  | product_categorizations        | 
  | products                       | 
  | profiles                       | 
  | region_validators              | 
  | role_assignments               | 
  | roles                          | 
  | schema_info                    | 
  | taggings                       | 
  | tags                           | 
  | tasks                          | 
  | thumbnails                     | 
  | users                          | 
  | validation_infos               | 
  +--------------------------------+
  27 rows in set (0.00 sec)

A seguir, faremos um relato sobre o papel de cada tabela no funcionamento do sistema:

== article_versions               

Os artigos posssuem controle de versão e cada versão é guardada nessa tabela.

== articles                       

Artigos são todo tipo de conteúdo que pode ser criado pelo usuário. Como textos, imagens e até mesmo pastas.

== articles_categories            

Os artigos são classificados por categorias. Esta tabela guarda as associações entre artigos e categorias.  

== blocks                         

Guarda as informações relativas aos blocos, que são apresentados em boxes na página do usuário.

== boxes                          

Representa as áreas onde os usuários podem anexar seus blocos.

== categories                     

São categorias do sistema, que incluem categorias de produto e regiões.

== categories_profiles           

Esta tabela guarda a associação entre categories e profiles.

== comments                       

Esta tabela guarda os comentários feitos nos artigos.

== consumptions                   

Representa os tipos de produtos que o usuário consome. 

== domains                        

Cada ambiente pode ter um ou mais domínios, nesta tabela está armazenado o domínio do ambiente.

== environments                   

Representa cada uma das redes sociais (ou ambiente) geridas pelo Noosfero.

== favorite_enteprises_people     

Representa os empreendimentos favoritos de um usuário.

== friendships                    

Esta tabela apresenta todos as relações de amizade.

== images                         

Guarda as informações sobre todas as imagens armazendas no sistema.

== product_categorizations        

Representa a associação entre produtos e categorias.

== products                       

Esta tabela guarda todos os produtos dos empreendimentos do sistema.

== profiles                       

É a entidade mais importante do sistema. Representa tanto pessoas, quanto comunidades, empreeendimentos e organizações.

== region_validators              

Relaciona as organizações validadoras com a região em que ela opera.

== role_assignments               

Associa um papel a um usuário, dando a ele permissões sobre um determinado recurso do sistema.

== roles                          

Apresenta todos os papéis que podem ser atribuídas aos usuários e agrega quais permissões um usuário com esse papel terá.

== schema_info                    

Guarda o número da migration no Rails.

== taggings                       

Associa uma tag a um artigo.

== tags                     

Esta tabela armazena uma tag que pode ser associada a artigos.

== tasks                          

Representa uma tarefa que pode ser atribuída a um usuário, comunidade ou empreendimento.

== thumbnails                     

Guarda informações sobre miniaturas de imagens.

== users                          

Esta tabela guarda informações de login de todos os usuários do sistema.

== validation_infos

Guarda a metodologia de validação de uma entidade validadora.

== Abaixo segue modelagem do Noosfero

link:../noosfero_tabelas_article.png

link:../noosfero_tabelas_category.png

link:../noosfero_tabelas_profile.png

link:../noosfero_tabelas_environment.png

link:../noosfero_tabelas_schema.png