Estou apenas começando com meu primeiro aplicativo da web Ruby on Rails. Eu tenho vários modelos, visualizações, controladores e assim por diante.
Estou querendo encontrar um bom lugar para definir definições de constantes verdadeiramente globais que se apliquem a todo o meu aplicativo. Em particular, eles se aplicam tanto na lógica dos meus modelos quanto nas decisões tomadas em meus pontos de vista. Não consigo encontrar nenhum lugar DRY para colocar essas definições em que estejam disponíveis para todos os meus modelos e também para todas as minhas visualizações.
Para dar um exemplo específico, quero uma constante COLOURS = ['white', 'blue', 'black', 'red', 'green']
. Isso é usado em todo o lugar, nos modelos e nas visualizações. Onde posso defini-lo em apenas um local para que seja acessível?
O que eu tentei:
- Variáveis de classe constante no arquivo model.rb às quais estão mais associadas, como
@@COLOURS = [...]
. Mas não consegui encontrar uma maneira sensata de defini-lo para que eu possa escrever em meus pontos de vistaCard.COLOURS
vez de algo parecido com um desastreCard.first.COLOURS
. - Um método no modelo, algo como
def colours ['white',...] end
- o mesmo problema. - Um método no application_helper.rb - é o que estou fazendo até agora, mas os auxiliares só estão acessíveis nas visualizações, não nos modelos
- Acho que posso ter tentado algo no application.rb ou environment.rb, mas esses não parecem realmente corretos (e também não parecem funcionar)
Não existe apenas uma maneira de definir algo que possa ser acessado a partir de modelos e de visualizações? Quero dizer, eu sei que modelos e visualizações devem ser separados, mas certamente em alguns domínios haverá momentos em que eles precisarão se referir ao mesmo conhecimento específico de domínio?
fonte
Respostas:
Se o seu modelo é realmente "responsável" pelas constantes, você deve colocá-las lá. Você pode criar métodos de classe para acessá-los sem criar uma nova instância de objeto:
Como alternativa, você pode criar variáveis de classe e um acessador. No entanto, isso é desencorajado, pois as variáveis de classe podem parecer surpreendentes com a herança e em ambientes com vários threads.
As duas opções acima permitem alterar a matriz retornada em cada chamada do método acessador, se necessário. Se você tiver uma constante verdadeiramente imutável, também poderá defini-la na classe de modelo:
Você também pode criar constantes globais acessíveis em qualquer lugar do inicializador, como no exemplo a seguir. Este é provavelmente o melhor lugar, se suas cores forem realmente globais e usadas em mais de um contexto de modelo.
Nota: quando definimos constantes acima, geralmente queremos
freeze
a matriz. Isso evita que outros códigos modifiquem mais tarde (inadvertidamente) a matriz adicionando, por exemplo, um novo elemento. Depois que um objeto é congelado, ele não pode mais ser alterado.fonte
config/initializers/my_constants.rb
caminho, lembre-se de reiniciar o servidor:touch tmp/restart.txt
def self.colours
exemplo não é ideal. Cada vez que você chamadef self.colours
, uma nova instância da matriz será retornada .#freeze
não vai ajudar neste caso. A melhor prática é declará-la como uma constante Ruby. Nesse caso, você sempre recuperará o mesmo objeto.class Card; COLOURS = ['white', 'blue'].freeze; def self.colours; COLOURS; end; end
Dito isso, a alocação de uma matriz em qualquer idioma pode ser potencialmente problemática; por um lado, está usando a memória sem motivo (bom). Se estiver carregando de um banco de dados e quiser armazenar em cache o valor, também é possível usar uma variável de instância de classe, que pode ser carregada com preguiça usando odef self.colours
método No entanto, concordamos com o aspecto da imutabilidade.Algumas opções:
Usando uma constante:
Preguiçoso carregado usando a variável de instância de classe:
Se for uma constante verdadeiramente global ( embora evite constantes globais dessa natureza ), você também pode considerar colocar uma constante de nível superior,
config/initializers/my_constants.rb
por exemplo.fonte
extend
o módulo da classe estará disponível comCard.COLOURS
.extend
seu não está funcionando para mim. Ao usarinclude
, posso acessar como:Card::COLOURS
/models
. É muito melhor se você criar um inicializador./models
, mas apenas se estiver dentro de um módulo, por exemplo,module Constants; COLOURS = ...; end
em um arquivo chamadomodels/constants.rb
.No Rails 4.2, você pode usar a
config.x
propriedade:Que estará disponível como:
Outro método para carregar a configuração personalizada:
Nos Rails 5 e 6 , você pode usar o
configuration
objeto diretamente para configuração personalizada, além deconfig.x
. No entanto, ele só pode ser usado para configuração não aninhada:Ele estará disponível como:
fonte
Rails.configuration.colours
melhor (embora eu gostaria que não fosse tão longo)config
é tão bom quantoconfiguration
. Podemos esperar para obter um atalho em algum ponto :)Se uma constante é necessária em mais de uma classe, eu a coloco em config / initializers / contant.rb sempre em todas as maiúsculas (a lista de estados abaixo é truncada).
Eles estão disponíveis através do aplicativo, exceto no código do modelo, como tal:
Para usar a constante em um modelo, use attr_accessor para disponibilizar a constante.
fonte
config/initializers/constants.rb
provavelmente seria uma escolha melhor emboraPara configurações em todo o aplicativo e constantes globais, recomendo usar o Settingslogic . Essas configurações são armazenadas no arquivo YML e podem ser acessadas a partir de modelos, visualizações e controladores. Além disso, você pode criar configurações diferentes para todos os seus ambientes:
Em algum lugar da visualização (prefiro métodos auxiliares para esse tipo de coisa) ou em um modelo que você pode obter, por exemplo, uma variedade de cores
Settings.colors.split(/\s/)
. É muito flexível. E você não precisa inventar uma bicicleta.fonte
Use um método de classe:
Em seguida
Model.colours
, retornará essa matriz. Como alternativa, crie um inicializador e agrupe as constantes em um módulo para evitar conflitos de espaço para nome.fonte
Tente manter todas as constantes em um só lugar. No meu aplicativo, criei a pasta constantes dentro dos inicializadores da seguinte maneira:
e geralmente mantenho tudo constante nesses arquivos.
No seu caso, você pode criar um arquivo na pasta constantes como
colors_constant.rb
colors_constant.rb
Não se esqueça de reiniciar o servidor
fonte
Outra opção, se você deseja definir suas constantes em um só lugar:
Mas ainda os torne visíveis globalmente sem precisar acessá-los de maneira totalmente qualificada:
fonte
Um local comum para colocar constantes globais em todo o aplicativo é o interior
config/application
.fonte
Normalmente, tenho um modelo / tabela de 'pesquisa' no meu programa de trilhos e o uso para as constantes. É muito útil se as constantes forem diferentes para ambientes diferentes. Além disso, se você planeja estendê-los, digamos que deseja adicionar 'amarelo' em uma data posterior, basta adicionar uma nova linha à tabela de pesquisa e concluir o processo.
Se você der permissões de administrador para modificar esta tabela, elas não entrarão em contato com você para manutenção. :) SECO.
Aqui está como meu código de migração se parece:
Eu uso o seeds.rb para preenchê-lo previamente.
fonte
A variável global deve ser declarada no
config/initializers
diretóriofonte
De acordo com sua condição, você também pode definir algumas variáveis ambientais e buscá-la
ENV['some-var']
no código ruby. Essa solução pode não ser adequada para você, mas espero que ajude outras pessoas.Exemplo: você pode criar arquivos diferentes
.development_env
,.production_env
,.test_env
e carregá-lo de acordo com seus ambientes de aplicativos, verifique este gen dotenv-rails que automatizam isso para o seu.fonte