From a4dbd768ce35c5c3394cc1c1a93025f71da3ead2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Pereira?= Date: Tue, 31 May 2016 19:57:29 +0200 Subject: [PATCH 1/2] Custom folder structure: initial documentation, code and structure folders --- CUSTOMIZE_ES.md | 214 ++++++++++++++++++++++++++ Gemfile | 2 + Gemfile_custom | 5 + app/assets/images/custom/.keep | 0 app/assets/javascripts/application.js | 1 + app/assets/javascripts/custom.js | 7 + app/assets/stylesheets/custom.scss | 5 +- app/models/custom/.keep | 0 app/views/custom/.keep | 0 config/application.rb | 13 ++ config/application_custom.rb | 4 + config/initializers/assets.rb | 4 + config/locales/custom/.keep | 0 spec/models/custom/.keep | 0 14 files changed, 254 insertions(+), 1 deletion(-) create mode 100644 CUSTOMIZE_ES.md create mode 100644 Gemfile_custom create mode 100644 app/assets/images/custom/.keep create mode 100644 app/assets/javascripts/custom.js create mode 100644 app/models/custom/.keep create mode 100644 app/views/custom/.keep create mode 100644 config/application_custom.rb create mode 100644 config/locales/custom/.keep create mode 100644 spec/models/custom/.keep diff --git a/CUSTOMIZE_ES.md b/CUSTOMIZE_ES.md new file mode 100644 index 000000000..71c3701e4 --- /dev/null +++ b/CUSTOMIZE_ES.md @@ -0,0 +1,214 @@ +# Personalización + +Puedes modificar consul y ponerle tu propia imagen, para esto debes primero hacer un fork de https://github.com/consul/consul creando un repositorio nuevo en Github. Puedes usar otro servicio como Gitlab, pero no te olvides de poner el enlace en el footer a tu repositorio en cumplimiento con la licencia de este proyecto (GPL Affero 3). + +Hemos creado una estructura específica donde puedes sobreescribir y personalizar la aplicación para que puedas actualizar sin que tengas problemas al hacer merge y se sobreescriban por error tus cambios. Intentamos que Consul sea una aplicación Ruby on Rails lo más plain vanilla posible para facilitar el acceso de nuevas desarrolladoras. + +## Ficheros y directorios especiales + +Para adaptarlo puedes hacerlo a través de los directorios que están en custom dentro de: + +* config/locales/custom/ +* app/assets/images/custom/ +* app/views/custom/ +* app/controllers/custom/ +* app/models/custom/ + +Aparte de estos directorios también cuentas con ciertos ficheros para: + +* app/assets/stylesheets/custom.css +* app/assets/javascripts/custom.js +* Gemfile_custom +* config/application.custom.rb + +### Internacionalización + +Si quieres modificar algún texto de la web deberías encontrarlos en los ficheros formato YML disponibles en *config/locales/*. Puedes leer la [guía de internacionalización](http://guides.rubyonrails.org/i18n.html) de Ruby on Rails sobre como funciona este sistema. + +Las adaptaciones los debes poner en el directorio *config/locales/custom/*, recomendamos poner solo los textos que quieras personalizar. Por ejemplo si quieres personalizar el texto de "Ayuntamiento de Madrid, 2016" que se encuentra en el footer en todas las páginas, primero debemos ubicar en que plantilla se encuentra (app/views/layouts/_footer.html.erb), vemos que en el código pone lo siguiente: +``` +<%= t("layouts.footer.copyright", year: Time.now.year) %> +``` + +Y que en el fichero config/locales/es.yml sigue esta estructura (solo ponemos lo relevante para este caso): + +``` +es: + layouts: + footer: + copyright: Ayuntamiento de Madrid, %{year} + +``` + +Si creamos el fichero config/locales/custom/es.yml y modificamos "Ayuntamiento de Madrid" por el nombre de la organización que se este haciendo la modificación. Recomendamos directamente copiar los ficheros config/locales/ e ir revisando y corrigiendo las que querramos, borrando las líneas que no querramos traducir. + +### Imágenes + +Si quieres sobreescribir alguna imagen debes primero fijarte el nombre que tiene, por defecto se encuentran en *app/assets/images*. Por ejemplo si quieres modificar *app/assets/images/logo_header.png* debes poner otra con ese mismo nombre en el directorio app/assets/images/custom. Los iconos que seguramente quieras modificar son: + +* apple-touch-icon-200.png +* icon_home.png +* logo_email.png +* logo_header.png +* map.jpg +* social-media-icon.png + +### Vistas (HTML) + +Si quieres modificar el HTML de alguna página puedes hacerlo copiando el HTML de *app/views* y poniendolo en *app/views/custom* respetando los subdirectorios que encuentres ahí. Por ejemplo si quieres modificar *app/views/pages/conditions.html* debes copiarlo y modificarla en app/views/custom/pages/conditions.html.erb + +### CSS + +Si quieres cambiar algun selector CSS (de las hojas de estilo) puedes hacerlo en el fichero *app/assets/stylesheets/custom.scss*. Por ejemplo si quieres cambiar el color del header (.top-links) puedes hacerlo agregando: + +``` +.top-links { + background: red; +} +``` + +Usamos un preprocesador de CSS, [SASS, con la sintaxis SCSS](http://sass-lang.com/guide). + +### Javascript + +Si quieres agregar código Javascript puedes hacerlo en el fichero *app/assets/javascripts/custom.js". Por ejemplo si quieres que salga una alerta puedes poner lo siguiente: + +``` +$(function(){ + alert('foobar'); +}); +``` + +### Modelos + +Si quieres agregar modelos nuevos, o modificar o agregar métodos a uno ya existente puedes hacerlo en *app/models/custom*. En el caso de los modelos antiguos debes primero hacer un require de la dependencia. + +Por ejemplo en el caso del Ayuntamiento de Madrid se requiere comprobar que el código postal durante la verificación sigue un cierto formato (empieza con 280). Esto se realiza creando este fichero en *app/models/custom/verification/residence.rb*: + +``` +require_dependency Rails.root.join('app', 'models', 'verification', 'residence').to_s + +class Verification::Residence + + validate :postal_code_in_madrid + validate :residence_in_madrid + + def postal_code_in_madrid + errors.add(:postal_code, I18n.t('verification.residence.new.error_not_allowed_postal_code')) unless valid_postal_code? + end + + def residence_in_madrid + return if errors.any? + + unless residency_valid? + errors.add(:residence_in_madrid, false) + store_failed_attempt + Lock.increase_tries(user) + end + end + + private + + def valid_postal_code? + postal_code =~ /^280/ + end + +end +``` + +No olvides poner los tests relevantes en *spec/models/custom*, siguiendo con el ejemplo pondriamos lo siguiente en *spec/models/custom/residence_spec.rb*: + + +``` +require 'rails_helper' + +describe Verification::Residence do + + let(:residence) { build(:verification_residence, document_number: "12345678Z") } + + describe "verification" do + + describe "postal code" do + it "should be valid with postal codes starting with 280" do + residence.postal_code = "28012" + residence.valid? + expect(residence.errors[:postal_code].size).to eq(0) + + residence.postal_code = "28023" + residence.valid? + expect(residence.errors[:postal_code].size).to eq(0) + end + + it "should not be valid with postal codes not starting with 280" do + residence.postal_code = "12345" + residence.valid? + expect(residence.errors[:postal_code].size).to eq(1) + + residence.postal_code = "13280" + residence.valid? + expect(residence.errors[:postal_code].size).to eq(1) + expect(residence.errors[:postal_code]).to include("In order to be verified, you must be registered in the municipality of Madrid.") + end + end + + end + +end +``` + +### Controladores + +TODO + +### Gemfile + +Para agregar librerías (gems) nuevas puedes hacerlo en el fichero *Gemfile_custom*. Por ejemplo si quieres agregar la gema [rails-footnotes](https://github.com/josevalim/rails-footnotes) debes hacerlo agregandole + +``` +gem 'rails-footnotes', '~> 4.0' +``` + +Y siguiendo el flujo clásico en Ruby on Rails (bundle install y seguir con los pasos específicos de la gema en la documentación) + +### application.rb + +Cuando necesites extender o modificar el *config/application.rb* puedes hacerlo a través del fichero *config/application_custom.rb*. Por ejemplo si quieres modificar el idioma por defecto al inglés pondrías lo siguiente: + + +``` +module Consul + class Application < Rails::Application + config.i18n.default_locale = :en + config.i18n.available_locales = [:en, :es] + end +end +``` + +Recuerda que para ver reflejado estos cambios debes reiniciar el servidor de desarrollo. + +### lib/ + +TODO + +### public/ + +TODO + +### Seeds + +TODO + +## Actualizar + +Te recomendamos que agregues el remote de consul para facilitar este proceso de merge: + +``` +$ git remote add consul https://github.com/consul/consul +``` + +Con esto puedes actualizarte con + +``` +git checkout -b consul_update +git pull consul master +``` diff --git a/Gemfile b/Gemfile index 50b9e37e9..ca56313fc 100644 --- a/Gemfile +++ b/Gemfile @@ -94,3 +94,5 @@ group :development do # Access an IRB console on exception pages or by using <%= console %> in views gem 'web-console', '~> 3.0' end + +eval_gemfile './Gemfile_custom' diff --git a/Gemfile_custom b/Gemfile_custom new file mode 100644 index 000000000..9d91e0680 --- /dev/null +++ b/Gemfile_custom @@ -0,0 +1,5 @@ +# Overrides and adds customized gems in this file +# Read more on documentation: +# * English: https://github.com/consul/consul/blob/master/CUSTOMIZE_EN.md#gemfile +# * Spanish: https://github.com/consul/consul/blob/master/CUSTOMIZE_ES.md#gemfile +# diff --git a/app/assets/images/custom/.keep b/app/assets/images/custom/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index a1b8dd70a..ca79ceb8b 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -45,6 +45,7 @@ //= require valuation_spending_proposal_form //= require embed_video //= require banners +//= require custom var initialize_modules = function() { App.Comments.initialize(); diff --git a/app/assets/javascripts/custom.js b/app/assets/javascripts/custom.js new file mode 100644 index 000000000..6c880b3a9 --- /dev/null +++ b/app/assets/javascripts/custom.js @@ -0,0 +1,7 @@ +// Overrides and adds customized javascripts in this file +// Read more on documentation: +// * English: https://github.com/consul/consul/blob/master/CUSTOMIZE_EN.md#javascript +// * Spanish: https://github.com/consul/consul/blob/master/CUSTOMIZE_ES.md#javascript +// +// + diff --git a/app/assets/stylesheets/custom.scss b/app/assets/stylesheets/custom.scss index c764f4ad2..090eb0342 100644 --- a/app/assets/stylesheets/custom.scss +++ b/app/assets/stylesheets/custom.scss @@ -1,2 +1,5 @@ // Overrides and adds customized styles in this file -// \ No newline at end of file +// Read more on documentation: +// * English: https://github.com/consul/consul/blob/master/CUSTOMIZE_EN.md#css +// * Spanish: https://github.com/consul/consul/blob/master/CUSTOMIZE_ES.md#css +// diff --git a/app/models/custom/.keep b/app/models/custom/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/app/views/custom/.keep b/app/views/custom/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/config/application.rb b/config/application.rb index 395251a52..3f2a0861a 100644 --- a/config/application.rb +++ b/config/application.rb @@ -1,3 +1,4 @@ + require File.expand_path('../boot', __FILE__) require 'rails/all' @@ -34,5 +35,17 @@ module Consul config.autoload_paths << Rails.root.join('lib') config.time_zone = 'Madrid' config.active_job.queue_adapter = :delayed_job + + # Consul specific custom overrides + # Read more on documentation: + # * English: https://github.com/consul/consul/blob/master/CUSTOMIZE_EN.md + # * Spanish: https://github.com/consul/consul/blob/master/CUSTOMIZE_ES.md + # + config.autoload_paths << "#{Rails.root}/app/controllers/custom" + config.autoload_paths << "#{Rails.root}/app/models/custom" + config.paths['app/views'].unshift(Rails.root.join('app', 'views', 'custom')) + end end + +require "./config/application_custom.rb" diff --git a/config/application_custom.rb b/config/application_custom.rb new file mode 100644 index 000000000..b99944bc7 --- /dev/null +++ b/config/application_custom.rb @@ -0,0 +1,4 @@ +module Consul + class Application < Rails::Application + end +end diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb index a13ed5320..543b39fc9 100644 --- a/config/initializers/assets.rb +++ b/config/initializers/assets.rb @@ -13,3 +13,7 @@ Rails.application.config.assets.precompile += %w( ckeditor/* ) Rails.application.config.assets.precompile += %w( ie_lt9.js ) Rails.application.config.assets.precompile += %w( stat_graphs.js ) Rails.application.config.assets.precompile += %w( print.css ) + +# Really ugly hack to putting app/assets/images/custom in front of app/assets/images +images_path = Rails.application.config.assets.paths +images_path = images_path.insert(0, Rails.root.join("app", "assets", "images", "custom").to_s) diff --git a/config/locales/custom/.keep b/config/locales/custom/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/spec/models/custom/.keep b/spec/models/custom/.keep new file mode 100644 index 000000000..e69de29bb From 24a9d77e6471263e7656b11dd51ded3106d963dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Pereira?= Date: Tue, 31 May 2016 19:57:37 +0200 Subject: [PATCH 2/2] Custom folder structure: verification residence for Madrid --- app/models/custom/verification/residence.rb | 29 ++++++++++++++++++ app/models/verification/residence.rb | 20 ------------ spec/models/custom/residence_spec.rb | 34 +++++++++++++++++++++ spec/models/residence_spec.rb | 23 -------------- 4 files changed, 63 insertions(+), 43 deletions(-) create mode 100644 app/models/custom/verification/residence.rb create mode 100644 spec/models/custom/residence_spec.rb diff --git a/app/models/custom/verification/residence.rb b/app/models/custom/verification/residence.rb new file mode 100644 index 000000000..1cbc6f7ab --- /dev/null +++ b/app/models/custom/verification/residence.rb @@ -0,0 +1,29 @@ + +require_dependency Rails.root.join('app', 'models', 'verification', 'residence').to_s + +class Verification::Residence + + validate :postal_code_in_madrid + validate :residence_in_madrid + + def postal_code_in_madrid + errors.add(:postal_code, I18n.t('verification.residence.new.error_not_allowed_postal_code')) unless valid_postal_code? + end + + def residence_in_madrid + return if errors.any? + + unless residency_valid? + errors.add(:residence_in_madrid, false) + store_failed_attempt + Lock.increase_tries(user) + end + end + + private + + def valid_postal_code? + postal_code =~ /^280/ + end + +end diff --git a/app/models/verification/residence.rb b/app/models/verification/residence.rb index 5756af2b3..cc24bb7c8 100644 --- a/app/models/verification/residence.rb +++ b/app/models/verification/residence.rb @@ -16,8 +16,6 @@ class Verification::Residence validate :allowed_age validate :document_number_uniqueness - validate :postal_code_in_madrid - validate :residence_in_madrid def initialize(attrs={}) self.date_of_birth = parse_date('date_of_birth', attrs) @@ -45,20 +43,6 @@ class Verification::Residence errors.add(:document_number, I18n.t('errors.messages.taken')) if User.where(document_number: document_number).any? end - def postal_code_in_madrid - errors.add(:postal_code, I18n.t('verification.residence.new.error_not_allowed_postal_code')) unless valid_postal_code? - end - - def residence_in_madrid - return if errors.any? - - unless residency_valid? - errors.add(:residence_in_madrid, false) - store_failed_attempt - Lock.increase_tries(user) - end - end - def store_failed_attempt FailedCensusCall.create({ user: user, @@ -97,8 +81,4 @@ class Verification::Residence self.document_number = self.document_number.gsub(/[^a-z0-9]+/i, "").upcase unless self.document_number.blank? end - def valid_postal_code? - postal_code =~ /^280/ - end - end diff --git a/spec/models/custom/residence_spec.rb b/spec/models/custom/residence_spec.rb new file mode 100644 index 000000000..ce0a95869 --- /dev/null +++ b/spec/models/custom/residence_spec.rb @@ -0,0 +1,34 @@ +require 'rails_helper' + +describe Verification::Residence do + + let(:residence) { build(:verification_residence, document_number: "12345678Z") } + + describe "verification" do + + describe "postal code" do + it "should be valid with postal codes starting with 280" do + residence.postal_code = "28012" + residence.valid? + expect(residence.errors[:postal_code].size).to eq(0) + + residence.postal_code = "28023" + residence.valid? + expect(residence.errors[:postal_code].size).to eq(0) + end + + it "should not be valid with postal codes not starting with 280" do + residence.postal_code = "12345" + residence.valid? + expect(residence.errors[:postal_code].size).to eq(1) + + residence.postal_code = "13280" + residence.valid? + expect(residence.errors[:postal_code].size).to eq(1) + expect(residence.errors[:postal_code]).to include("In order to be verified, you must be registered in the municipality of Madrid.") + end + end + + end + +end diff --git a/spec/models/residence_spec.rb b/spec/models/residence_spec.rb index ce151eaee..968a80e62 100644 --- a/spec/models/residence_spec.rb +++ b/spec/models/residence_spec.rb @@ -30,29 +30,6 @@ describe Verification::Residence do expect(residence.errors[:date_of_birth]).to include("You must be at least 16 years old") end - describe "postal code" do - it "should be valid with postal codes starting with 280" do - residence.postal_code = "28012" - residence.valid? - expect(residence.errors[:postal_code].size).to eq(0) - - residence.postal_code = "28023" - residence.valid? - expect(residence.errors[:postal_code].size).to eq(0) - end - - it "should not be valid with postal codes not starting with 280" do - residence.postal_code = "12345" - residence.valid? - expect(residence.errors[:postal_code].size).to eq(1) - - residence.postal_code = "13280" - residence.valid? - expect(residence.errors[:postal_code].size).to eq(1) - expect(residence.errors[:postal_code]).to include("In order to be verified, you must be registered in the municipality of Madrid.") - end - end - it "should validate uniquness of document_number" do user = create(:user) residence.user = user