portaldacalheta.pt
  • Principal
  • Noticias Do Mundo
  • Lucratividade E Eficiência
  • Ágil
  • Família
Processo Interno

Um guia para motores Rails na natureza: exemplos do mundo real de motores Rails em ação



Por que os Rails Engines não são usados ​​com mais frequência? Não sei a resposta, mas acho que a generalização de 'Tudo é um motor' escondeu os domínios do problema que eles podem ajudar a resolver.

O soberbo Documentação do Rails Guide para começar a usar o Rails Engines, consulte quatro exemplos populares de implementações do Rails Engine: Forem, Devise, Spree e RefineryCMS. Esses são casos de uso do mundo real fantásticos para Engines, cada um usando uma abordagem diferente para integração com um aplicativo Rails.



Todo guia Rails deve cobrir o tópico de padrões de projeto de engines Rails e seus exemplos.



Examinar partes de como essas joias são configuradas e compostas fornecerá Desenvolvedores de Ruby on Rails conhecimento valioso de quais padrões ou técnicas são experimentados e testados na natureza, então, quando chegar a hora, você terá algumas opções extras para avaliar.



Eu espero que você tenha uma familiaridade superficial de como um Engine funciona, então se você sentir que algo não está somando muito, por favor leia o mais excelente Guia Rails Introdução aos motores .

Sem mais delongas, vamos nos aventurar no mundo selvagem dos exemplos de engine Rails!



o retorno de chamada não é um nó de função js

Forem

Um motor para Rails que pretende ser o melhor pequeno sistema de fórum de todos os tempos

Esta joia segue a direção do Guia Rails sobre Motores ao pé da letra. É um exemplo considerável e examinar seu repositório lhe dará uma ideia de até onde você pode esticar a configuração básica.



É uma gem de mecanismo único que usa algumas técnicas para se integrar ao aplicativo principal.

module ::Forem class Engine

A parte interessante aqui é o Decorators.register! método de classe, exposto pela gema Decorators. Ele encapsula o carregamento de arquivos que não seriam incluídos no processo de carregamento automático do Rails. Você deve se lembrar de que usar require explícito | declarações estragam o recarregamento automático no modo de desenvolvimento, portanto, este é um salva-vidas! Será mais claro usar o exemplo do Guia para ilustrar o que está acontecendo:



config.to_prepare do Dir.glob(Rails.root + 'app/decorators/**/*_decorator*.rb').each do |c| require_dependency(c) end end

A maior parte da mágica para a configuração do Forem acontece na definição do módulo principal superior de Forem. Este arquivo depende de um user_class variável sendo definida em um arquivo inicializador:

Forem.user_class = 'User'

Você consegue isso usando mattr_accessor mas está tudo no Guia do Rails, então não vou repetir isso aqui. Com isso no lugar, Forem então decora a classe de usuário com tudo o que precisa para executar seu aplicativo:



module Forem class <'Forem::Post', :foreign_key => 'user_id' # ... def forem_moderate_posts? Forem.moderate_first_post && !forem_approved_to_post? end alias_method :forem_needs_moderation?, :forem_moderate_posts? # ...

O que acaba sendo bastante! Eu cortei a maioria, mas deixei em uma definição de associação, bem como um método de instância para mostrar o tipo de linhas que você pode encontrar lá.

Vislumbrar todo o arquivo pode mostrar como pode ser gerenciável portar parte de seu aplicativo para reutilização em um mecanismo.



Decorar é o nome do jogo no uso padrão do mecanismo. Como um usuário final da gema, você pode sobrescrever o modelo, visualização e controladores criando suas próprias versões das classes usando o caminho do arquivo e as convenções de nomenclatura de arquivo estabelecidas no README da gema decoradora. Porém, há um custo associado a essa abordagem, especialmente quando o Engine recebe uma atualização de versão principal - a manutenção de manter suas decorações funcionando pode rapidamente sair do controle. Não estou citando Forem aqui, acredito que eles são firmes em manter uma funcionalidade básica bem unida, mas tenha isso em mente se você criar um Motor e decidir fazer uma revisão.

Vamos recapitular: este é o padrão de design do motor Rails padrão que depende dos usuários finais que decoram visualizações, controladores e modelos, juntamente com a configuração de configurações básicas por meio de arquivos de inicialização. Isso funciona bem para uma funcionalidade muito focada e relacionada.

Lema

Uma solução de autenticação flexível para Rails

Você descobrirá que um Engine é muito semelhante a uma aplicação Rails, com views, controllers e models diretórios. Devise é um bom exemplo de encapsular um aplicativo e expor um ponto de integração conveniente. Vamos ver como isso funciona exatamente.

Você reconhecerá essas linhas de código se tiver sido um desenvolvedor Rails por mais de algumas semanas:

como obter os números dos cartões de crédito das pessoas online
class User

Cada parâmetro passado para o devise método representa um módulo dentro do Devise Engine. Existem dez desses módulos no total que herdam do familiar ActiveSupport::Concern. Eles estendem seu User classe invocando devise método dentro de seu escopo.

Ter este tipo de ponto de integração é muito flexível, você pode adicionar ou remover qualquer um desses parâmetros para alterar o nível de funcionalidade que você precisa que o Engine execute. Isso também significa que você não precisa codificar qual model você gostaria de usar em um arquivo inicializador, como sugerido pelo Rails Guide on Engines. Em outras palavras, isso não é necessário:

Devise.user_model = 'User'

Essa abstração também significa que você pode aplicar isso a mais de um modelo de usuário dentro do mesmo aplicativo (admin e user por exemplo), enquanto a abordagem do arquivo de configuração deixaria você amarrado a um único modelo com autenticação. Este não é o maior argumento de venda, mas ilustra uma maneira diferente de resolver um problema.

O Devise estende ActiveRecord::Base com seu próprio módulo que inclui o devise definição do método:

# lib/devise/orm/active_record.rb ActiveRecord::Base.extend Devise::Models

Qualquer classe que herde de ActiveRecord::Base agora terá acesso aos métodos de classe definidos em Devise::Models:

#lib/devise/models.rb module Devise module Models # ... def devise(*modules) selected_modules = modules.map(&:to_sym).uniq # ... selected_modules.each do |m| mod = Devise::Models.const_get(m.to_s.classify) if mod.const_defined?('ClassMethods') class_mod = mod.const_get('ClassMethods') extend class_mod # ... end include mod end end # ... end end

(Eu removi muitos códigos (# ...) para destacar as partes importantes.)

Parafraseando o código, para cada nome de módulo passado para o devise método que somos:

  • carregando o módulo que especificamos que reside em Devise::Models (Devise::Models.const_get(m.to_s.classify)
  • estendendo o User classe com ClassMethods módulo se tiver um
  • incluem o módulo especificado (include mod) para adicionar seus métodos de instância à classe que chama o devise método (User)

Se você quiser criar um módulo que possa ser carregado dessa forma, você precisará certificar-se de que segue o ActiveSupport::Concern usual | interface, mas o namespace sob o Devise:Models pois é aqui que procuramos recuperar a constante:

module Devise module Models module Authenticatable extend ActiveSupport::Concern included do # ... end module ClassMethods # ... end end end end

Ufa.

Se você já usou o Rails ’Concerns antes e experimentou a reutilização que eles oferecem, então você pode apreciar as sutilezas desta abordagem. Resumindo, dividir a funcionalidade dessa maneira torna o teste mais fácil, sendo abstraído de um ActiveRecord modelo e tem uma sobrecarga menor do que o padrão usado pelo Forem quando se trata de estender a funcionalidade.

Este padrão consiste em dividir sua funcionalidade em Rails Concerns e expor um ponto de configuração para incluir ou excluir dentro de um determinado escopo. Um motor formado dessa maneira é conveniente para o usuário final - um fator que contribui para o sucesso e a popularidade do Devise. E agora você também sabe fazer!

Farra

Uma solução de e-commerce de código aberto completa para Ruby on Rails

tutorial do angular 5 para iniciantes passo a passo

Spree fez um esforço colossal para colocar seu aplicativo monolítico sob controle com uma mudança para o uso de motores. O projeto de arquitetura com o qual eles estão trabalhando agora é uma joia “Spree” que contém muitas joias do motor.

Esses motores criam partições no comportamento que você pode estar acostumado a ver em um aplicativo monolítico ou espalhado entre os aplicativos:

  • spree_api (RESTful API)
  • spree_frontend (componentes voltados para o usuário)
  • spree_backend (área administrativa)
  • spree_cmd (ferramentas de linha de comando)
  • spree_core (Modelos e Mailers, os componentes básicos do Spree sem os quais ele não pode ser executado)
  • spree_sample (dados de amostra)

A gema abrangente os une, deixando o desenvolvedor com uma escolha no nível de funcionalidade a ser exigido. Por exemplo, você pode executar apenas com spree_core Engine e envolva sua própria interface em torno dele.

A principal joia do Spree requer estes motores:

# lib/spree.rb require 'spree_core' require 'spree_api' require 'spree_backend' require 'spree_frontend'

Cada Engine precisa então personalizar seu engine_name e root caminho (o último geralmente apontando para a gema de nível superior) e se configurarem conectando-se ao processo de inicialização:

# api/lib/spree/api/engine.rb require 'rails/engine' module Spree module Api class Engine :load_config_initializers do |app| app.config.spree = Spree::Core::Environment.new end # ... end end end

Você pode ou não reconhecer este método inicializador: ele é parte de Railtie e é um gancho que dá a oportunidade de adicionar ou remover etapas da inicialização do framework Rails. Spree depende muito desse gancho para configurar seu ambiente complexo para todos os seus motores.

Usando o exemplo acima em tempo de execução, você terá acesso às suas configurações acessando o nível superior Rails constante:

Rails.application.config.spree

Com este guia de padrão de design do motor Rails acima, poderíamos encerrar o dia, mas Spree tem uma tonelada de código incrível, então vamos mergulhar em como eles utilizam a inicialização para compartilhar a configuração entre os motores e o aplicativo Rails principal.

O Spree possui um sistema de preferências complexo que carrega adicionando uma etapa ao processo de inicialização:

# api/lib/spree/api/engine.rb initializer 'spree.environment', :before => :load_config_initializers do |app| app.config.spree = Spree::Core::Environment.new end

Aqui, estamos anexando a app.config.spree um novo Spree::Core::Environment instância. Dentro da aplicação rails você poderá acessar isto via Rails.application.config.spree de qualquer lugar - modelos, controladores, visualizações.

Continuando para baixo, o Spree::Core::Environment classe que criamos tem a seguinte aparência:

module Spree module Core class Environment attr_accessor :preferences def initialize @preferences = Spree::AppConfiguration.new end end end end

Ele expõe um :preferences variável definida para uma nova instância de Spree::AppConfiguration classe, que por sua vez usa um preference método definido no Preferences::Configuration classe para definir opções com padrões para a configuração geral do aplicativo:

module Spree class AppConfiguration

Não vou mostrar o Preferences::Configuration porque vai levar um pouco de explicação, mas essencialmente é um açúcar sintático para obter e definir preferências. (Na verdade, esta é uma simplificação exagerada de sua funcionalidade, pois o sistema de preferências salvará valores diferentes do padrão para preferências existentes ou novas no banco de dados, para qualquer ActiveRecord classe com uma coluna :preference mas você não precisa saber disso.)

Aqui está uma dessas opções em ação:

module Spree class Calculator

Calculadoras controlam todos os tipos de coisas no Spree - custos de remessa, promoções, ajustes de preços de produtos - portanto, ter um mecanismo para trocá-los dessa maneira aumenta a extensibilidade do motor.

Uma das muitas maneiras de sobrescrever as configurações padrão para essas preferências é dentro de um inicializador no aplicativo Rails principal:

# config/initializergs/spree.rb Spree::Config do |config| config.admin_interface_logo = 'company_logo.png' end

Se você leu o RailsGuide em motores , considerando seus padrões de projeto ou construindo você mesmo um Engine, você saberá que é trivial expor um setter em um arquivo inicializador para alguém usar. Então você deve estar se perguntando, por que tanto barulho com o sistema de configuração e preferência? Lembre-se de que o sistema de preferência resolve um problema de domínio para Spree. Conectar-se ao processo de inicialização e obter acesso ao framework Rails pode ajudá-lo a atender seus requisitos de forma sustentável.

Este padrão de design de mecanismo foca no uso do framework Rails como a constante entre suas muitas partes móveis para armazenar configurações que (geralmente) não mudam no tempo de execução, mas mudam entre as instalações de aplicativos.

Se você já tentou etiqueta branca um aplicativo Rails, você pode estar familiarizado com este cenário de preferências e ter sentido a dor das complicadas tabelas de “configurações” do banco de dados em um longo processo de configuração para cada novo aplicativo. Agora você sabe que um caminho diferente está disponível e isso é incrível - high five!

RefineryCMS

Um sistema de gerenciamento de conteúdo de código aberto para Rails

c ++ da maneira mais difícil

Convenção sobre configuração de alguém? Os Rails Engines podem definitivamente parecer mais um exercício de configuração às vezes, mas o RefineryCMS lembra um pouco da magia do Rails. Este é todo o conteúdo de lib diretório:

# lib/refinerycms.rb require 'refinery/all' # lib/refinery/all.rb %w(core authentication dashboard images resources pages).each do |extension| require 'refinerycms-#{extension}' end

Uau. Se você não pode dizer com isso, a equipe da Refinaria realmente sabe o que está fazendo. Eles rolam com o conceito de um extension que é, em essência, outro motor. Como o Spree, ele tem uma gema de costura abrangente, mas usa apenas dois pontos e reúne uma coleção de motores para oferecer seu conjunto completo de funcionalidades.

Extensões também são criadas por usuários do Engine, para criar seu próprio mash-up de recursos CMS para blogs, notícias, portfólio, depoimentos, investigações, etc. (é uma longa lista), todos ligados ao RefineryCMS central.

Este projeto pode chamar sua atenção por sua abordagem modular, e Refinery é um ótimo exemplo desse padrão de projeto Rails. 'Como funciona?' Eu ouço você perguntar.

O core motor mapeia alguns ganchos para os outros motores usarem:

# core/lib/refinery/engine.rb module Refinery module Engine def after_inclusion(&block) if block && block.respond_to?(:call) after_inclusion_procs << block else raise 'Anything added to be called after_inclusion must be callable (respond to #call).' end end def before_inclusion(&block) if block && block.respond_to?(:call) before_inclusion_procs << block else raise 'Anything added to be called before_inclusion must be callable (respond to #call).' end end private def after_inclusion_procs @@after_inclusion_procs ||= [] end def before_inclusion_procs @@before_inclusion_procs ||= [] end end end

Como você pode ver o before_inclusion e after_inclusion apenas armazene uma lista de procs que serão executados mais tarde. O processo de inclusão da Refinaria estende os aplicativos Rails carregados atualmente com controladores e ajudantes da Refinaria. Aqui está um em ação:

# authentication/lib/refinery/authentication/engine.rb before_inclusion do [Refinery::AdminController, ::ApplicationController].each do |c| Refinery.include_once(c, Refinery::AuthenticatedSystem) end end

Tenho certeza de que você colocou métodos de autenticação em seu ApplicationController e AdminController antes, essa é uma maneira programática de fazer isso.

Qual das alternativas a seguir é verdadeira para um teste de unidade?

Analisar o restante do arquivo do mecanismo de autenticação nos ajudará a reunir alguns outros componentes importantes:

module Refinery module Authentication class Engine <::Rails::Engine extend Refinery::Engine isolate_namespace Refinery engine_name :refinery_authentication config.autoload_paths += %W( #{config.root}/lib ) initializer 'register refinery_user plugin' do Refinery::Plugin.register do |plugin| plugin.pathname = root plugin.name = 'refinery_users' plugin.menu_match = %r{refinery/users$} plugin.url = proc { Refinery::Core::Engine.routes.url_helpers.admin_users_path } end end end config.after_initialize do Refinery.register_extension(Refinery::Authentication) end # ... end end

Sob o capô, as extensões da Refinaria usam um Plugin sistema. O initializer etapa parecerá familiar a partir da análise de código do Spree, aqui estamos apenas encontrando o register requisitos de métodos a serem adicionados à lista de Refinery::Plugins que o core extensão mantém registro de, e Refinery.register_extension apenas adiciona o nome do módulo a uma lista armazenada em um acessador de classe.

Aqui está um choque: o Refinery::Authentication classe é realmente um invólucro em torno do Devise, com alguma personalização. Então, são tartarugas até o fim!

As extensões e plug-ins são conceitos que a Refinery desenvolveu para suportar seu rico ecossistema de aplicativos e ferramentas de mini-rails - pense rake generate refinery:engine. O padrão de design aqui difere do Spree, impondo uma API adicional em torno do Rails Engine para auxiliar no gerenciamento de sua composição.

O idioma “The Rails Way” está no cerne da Refinaria, cada vez mais presente em seus aplicativos mini-rails, mas de fora você não saberia disso. Projetar limites no nível de composição do aplicativo é tão importante, possivelmente mais, do que criar uma API limpa para suas classes e módulos usados ​​em seus aplicativos Rails.

Encapsular o código sobre o qual você não tem controle direto é um padrão comum, é uma previsão na redução do tempo de manutenção para quando o código for alterado, limitando o número de locais em que você precisará fazer alterações para oferecer suporte a atualizações. Aplicar essa técnica junto com a funcionalidade de particionamento cria uma plataforma flexível para composição, e aqui está um exemplo do mundo real bem debaixo do seu nariz - tenho que amar o código aberto!

Conclusão


Vimos quatro abordagens para projetar padrões de engine Rails analisando joias populares sendo usadas em aplicações do mundo real. Vale a pena ler seus repositórios para aprender com uma vasta experiência já aplicada e iterada. Fique de pé sobre os ombros dos gigantes.

Neste guia Rails, nos concentramos nos padrões de design e técnicas para integrar os Rails Engines e os aplicativos Rails de seus usuários finais, para que você possa adicionar o conhecimento deles ao seu Correia de ferramentas de trilhos .

Espero que você tenha aprendido tanto quanto eu ao revisar este código e se sinta inspirado a dar uma chance aos Rails Engines quando eles forem adequados. Um grande obrigado aos mantenedores e contribuintes das joias que revisamos. Bom trabalho pessoal!

Relacionado: Truncamento de carimbo de data / hora: um conto de Ruby on Rails ActiveRecord

Como Obter Clientes de Consultoria - Uma Entrevista com Steve Blank

Processos Financeiros

Como Obter Clientes de Consultoria - Uma Entrevista com Steve Blank
Como criar uma estrutura de design eficaz (inclui uma estrutura de interface de usuário de esboço grátis)

Como criar uma estrutura de design eficaz (inclui uma estrutura de interface de usuário de esboço grátis)

Design De Iu

Publicações Populares
Quem, o quê e por quê - um guia para métodos de teste do usuário
Quem, o quê e por quê - um guia para métodos de teste do usuário
Aflição financeira em uma crise: você não pode prever, você pode se preparar
Aflição financeira em uma crise: você não pode prever, você pode se preparar
Bangladesh condena seis militantes à morte por matar dois ativistas gays
Bangladesh condena seis militantes à morte por matar dois ativistas gays
Mães solteiras na arte de criar filhos sozinhas
Mães solteiras na arte de criar filhos sozinhas
Vender uma empresa para valor máximo em um mercado desafiador de fusões e aquisições
Vender uma empresa para valor máximo em um mercado desafiador de fusões e aquisições
 
Robo-conselheiro Risco de portfólio da indústria: eficiência ou redução de cantos?
Robo-conselheiro Risco de portfólio da indústria: eficiência ou redução de cantos?
EUA: corrida para prefeito de Honolulu segue para segundo turno
EUA: corrida para prefeito de Honolulu segue para segundo turno
13 podcasts que todo designer deve ouvir
13 podcasts que todo designer deve ouvir
Vazamentos de Panama Papers podem dar a Sanders algum poder de fogo contra o rival Clinton
Vazamentos de Panama Papers podem dar a Sanders algum poder de fogo contra o rival Clinton
Com 21 anos e raízes de Kerala, é o mais jovem na lista de MBE do Queen
Com 21 anos e raízes de Kerala, é o mais jovem na lista de MBE do Queen
Publicações Populares
  • melhor aplicativo de banco de dados para Android
  • modelo de previsão de fluxo de caixa semanal
  • o que é um arquivo de bootstrap
  • modelo de documento de design técnico simples
  • atributo de classe vs atributo de instância
  • você tem um usuário que está tendo problemas para salvar seu trabalho. o que você deve ter cuidado para não esquecer?
Categorias
  • Noticias Do Mundo
  • Lucratividade E Eficiência
  • Ágil
  • Família
  • © 2022 | Todos Os Direitos Reservados

    portaldacalheta.pt