= 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 + "
#{referencias}
" 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 ' 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

<%= _('Sending article to %s') % @person.name %>

<% 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.
  • <%= 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' %>
  • = 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