Update models customization documentation
This commit is contained in:
@@ -1,75 +1,63 @@
|
||||
# Models
|
||||
# Customizing models
|
||||
|
||||
If you need to create new models or customize existent ones, you can do it so at the `app/models/custom` folder. Keep in mind that for old models you'll need to firstly require the dependency.
|
||||
In order to create new models or customize existing ones, you can use the `app/models/custom/` folder.
|
||||
|
||||
For example for Madrid's City Hall fork its required to check the zip code's format (it always starts with 280 followed by 2 digits). That check is at `app/models/custom/verification/residence.rb`:
|
||||
If you're adding a new model that doesn't exist in the original Consul Democracy, simply add it to that folder.
|
||||
|
||||
If, on the other hand, you are changing a model that exists in the application, create a file in `app/models/custom/` with same name as the file you're changing. For example, if you're changing the `app/models/budget/investment.rb` file, create a file named `app/models/custom/budget/investment.rb` and require the original one:
|
||||
|
||||
```ruby
|
||||
load Rails.root.join("app", "models", "verification", "residence.rb")
|
||||
load Rails.root.join("app", "models", "budget", "investment.rb")
|
||||
|
||||
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?
|
||||
class Budget
|
||||
class Investment
|
||||
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
|
||||
```
|
||||
|
||||
Do not forget to cover your changes with a test at the `spec/models/custom` folder. Following the example we could create `spec/models/custom/residence_spec.rb`:
|
||||
Since the custom file requires the original one, at this point, the custom model will behave exactly as the original.
|
||||
|
||||
Note that, if we do not require the original file, that file won't be loaded and the custom model will do nothing, which will likely result in errors.
|
||||
|
||||
## Adding new methods
|
||||
|
||||
In order to add a new method, simply add the new code to the model. For example, let's add a scope that returns the investments created last month:
|
||||
|
||||
```ruby
|
||||
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
|
||||
load Rails.root.join("app", "models", "budget", "investment.rb")
|
||||
|
||||
class Budget
|
||||
class Investment
|
||||
scope :last_month, -> { where(created_at: 1.month.ago..) }
|
||||
end
|
||||
|
||||
end
|
||||
```
|
||||
|
||||
With this code, the custom model will have all the methods of the original model (because it loads the original file) plus the `last_month` scope.
|
||||
|
||||
## Modifying existing methods
|
||||
|
||||
When modifying existing methods, it is strongly recommended that, when possible, **your custom code calls the original code** and only modifies the cases where it should behave differently. This way, when upgrading to a new version of Consul Democracy that updates the original methods, your custom methods will automatically include the modifications in the original code as well. Sometimes this won't be possible, though, which means you might need to change your custom method when upgrading.
|
||||
|
||||
For example, to change the common abilities model so only verified users can create comments, we'll create a file `app/models/custom/abilities/common.rb` with the following content:
|
||||
|
||||
```ruby
|
||||
load Rails.root.join("app", "models", "abilities", "common.rb")
|
||||
|
||||
module Abilities
|
||||
class Common
|
||||
alias_method :consul_initialize, :initialize # create a copy of the original method
|
||||
|
||||
def initialize(user)
|
||||
consul_initialize(user) # call the original method
|
||||
cannot :create, Comment # undo the permission added in the original method
|
||||
|
||||
if user.level_two_or_three_verified?
|
||||
can :create, Comment
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
You can find another example in the `app/models/custom/setting.rb` file.
|
||||
|
||||
@@ -1,75 +1,63 @@
|
||||
# Modelos
|
||||
# Personalización de 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.
|
||||
Si quieres agregar modelos nuevos, o modificar o agregar métodos a uno ya existente, puedes utilizar el directorio `app/models/custom/`.
|
||||
|
||||
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`:
|
||||
Si estás añadiendo un nuevo modelo que no existe en el código original de Consul Democracy, simplemente añade el modelo a ese directorio.
|
||||
|
||||
Si, por el contrario, estás cambiando un modelo que existe en la aplicación, crea un fichero en `app/models/custom/` con el mismo nombre que el fichero que estás cambiando. Por ejemplo, para cambiar el fichero `app/models/budget/investment.rb`, crea un fichero llamado `app/models/custom/budget/investment.rb` que cargue el original:
|
||||
|
||||
```ruby
|
||||
load Rails.root.join("app", "models", "verification", "residence.rb")
|
||||
load Rails.root.join("app", "models", "budget", "investment.rb")
|
||||
|
||||
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?
|
||||
class Budget
|
||||
class Investment
|
||||
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`:
|
||||
Como el fichero personalizado carga el original, con este código el modelo personalizado se comportará exactamente igual que el original.
|
||||
|
||||
Nótese que, si no se carga el fichero original, el modelo personalizado no hará nada, lo cual hará que la aplicación no se comporte correctamente.
|
||||
|
||||
## Añadir nuevos métodos
|
||||
|
||||
Para añadir un método nuevo, simplemente añade el nuevo código al modelo. Por ejemplo, para añadir un método de tipo "scope" que devuelva los proyectos de gasto creados durante el último mes:
|
||||
|
||||
```ruby
|
||||
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
|
||||
load Rails.root.join("app", "models", "budget", "investment.rb")
|
||||
|
||||
class Budget
|
||||
class Investment
|
||||
scope :last_month, -> { where(created_at: 1.month.ago..) }
|
||||
end
|
||||
|
||||
end
|
||||
```
|
||||
|
||||
Con este código, el modelo personalizado tendrá todos los métodos del modelo original (ya que carga el archivo original) más el método de tipo "scope" `last_month`.
|
||||
|
||||
## Modificar métodos existentes
|
||||
|
||||
Al modificar métodos existentes, recomendamos encarecidamente que, siempre que sea posible, **tu código personalizado llame al código original** y solamente modifique los casos en que debería comportarse de forma diferente. De este modo, al actualizar a una nueva versión de Consul Democracy que actualice los métodos originales, tus métodos personalizados incluirán las modificaciones del código original automáticamente. En ocasiones, hacer esto no será posible, con lo cual tendrás que cambiar tu método personalizado al actualizar.
|
||||
|
||||
Por ejemplo, para cambiar el modelo `Abilities::Common` para que solamente los usuarios verificados puedan crear comentarios, crearemos el archivo `app/models/custom/abilities/common.rb` con el siguiente contenido:
|
||||
|
||||
```ruby
|
||||
load Rails.root.join("app", "models", "abilities", "common.rb")
|
||||
|
||||
module Abilities
|
||||
class Common
|
||||
alias_method :consul_initialize, :initialize # create a copy of the original method
|
||||
|
||||
def initialize(user)
|
||||
consul_initialize(user) # call the original method
|
||||
cannot :create, Comment # undo the permission added in the original method
|
||||
|
||||
if user.level_two_or_three_verified?
|
||||
can :create, Comment
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
Puedes encontrar otro ejemplo de modelo personalizado en el archivo `app/models/custom/setting.rb`.
|
||||
|
||||
Reference in New Issue
Block a user