Applicación Rails que sirve el sitio www.yavende.com.
El proyecto tiene cierto nivel de doc coverage provisto por YARD.
Examinar doc/index.html.
El scope del proyecto abarca proveer un front en donde usuarios anónimos pueden crear avisos de venta de autos, buscarlos, y efectuar algunas operaciónes relacionadas con el aviso, como denunciar que el aviso fue publicado por una agencía, o recuperar el link de edición.
No hay login, por lo que la edición de un aviso se hace mediante un link que contiene un token en la url que es provisto al dueño del aviso por mail.
Para la parte del administrador, es posible ver y crear y editar avisos, administrar las marcas, modelos y versiones de auto, importar modelos de auto por CSV, CMS, y administrar usuarios.
La app consiste de una single page hecha en angular, una API Rest pensada para ser consumida desde el front y un backend hecho con Administrate.
# config/routes.rb
# ...
namespace :admin do
# ...
end
namespace :api do
# ...
end
controller :single_page do
get "/templates/(*path)", action: :render_template
root action: :index
get "*path", action: :index
end
# ...
Gran parte de los assets para el front estan instalados con [bower-rails][1], una gema que permite appendear los packetes instalados con bower directamente en los load_paths de sprockets.
CarListing es el modelo que represanta los avisos. Importante: debido a un requerimiento
de negocio, cuando los avisos son updateados desde del front, generan una copia
de si mismos con el objecto de persistir al mismo tiempo, el aviso no aprobado
con los nuevos cambios, y el aviso aprobado que se tiene que mostrar en los listados
de búsqueda.
Esta funcionalidad esta encapsulada en los módulos Approvable y Versionable.
Example usage:
class CarListing < ActiveRecord::Base
include Approvable
# ...
self.options_for_clone = {
include: [
:inspector, :car, :seller,
:publication_manager, :sale_manager,
:manager, :auditor,
car: %i[images location],
seller: %i[location]
],
exclude: :validate_terms_of_service
}
# ...
end
CarListing.first.update(price: 2, create_clone: true)
donde options_for_clone se pasa directamente a [deep_clone][2].
Por otro lado, CarListing tiene subtipos como CarListing::Classic
con el objecto de encapsular validaciones distintas y otro comportamiento especial.
Los avisos tienen un Car, y el auto tiene una Car::Version, que pertenece a un Car::Model,
que a su vez pertenece a un Car::Brand.
Este arbol de marcas, modelos y versiones es importable por CSV. El código que se encarga de ello
está en Car::Version::Import. Esta clase es un modelo y se encarga de persistir y parsear el archivo
CSV, lo cual se debería hacer en background. Está preparado para aceptar CSV en el siguiente formato:
nombre_de_la_marca, nombre_del_modelo, nombre_de_la_version, 1990, 1991, 1992, 1993, 1994, [...]
FORD , FOCUS, , 1.6 GT , 1 , , , 1 ,
Lo que se traduce en la creación de una marca con mobre FORD, si no existe, un modelo FOCUS,
una versión 1.6 GT con años [1990, 1993].
Las búsquedas se implementaron con un poco de ayuda de [searchlight][3]. Todas las búequedas heredan de
Abstract Search, una clase que encapsula un poco el boiler plate que se repite en todas las búequedas,
y provee un pequeño DSL opcional que permite definir creiteriods de búsqueda en una sola línea.
Más información en YARD.
Todo el código de angular esta en app/assets/javascripts/angular/**/*. Presenta la siguiente estructura:
angular
|--app # donde se declara el modulo `yaComparaFront`
|--config # bloques `angluar.module("yaComparaFront").config` para configuración de plugins
|--initializers # código que se corre antes de que angular empieze a dibujar la app
|--directives
|--factories
|--services
Los clientes de javascript que se comunican con la API usan [angularjs-rails-resource][4] y necesitan de
un interceptor de request RestErrorsInterceptor que toma los errores que viene de la API y los
injectan en la instancia y sus associaciones anidadas. Este comportamiento depende profundamente de lo
implementado en su contraparte en ruby RestfulController::ErrorsSerializer.
Importante que en produción uglifier este configurando con:
config.assets.js_compressor = Uglifier.new(mangle: false)
.. para no romper el dependency injection de angular cuando uglifier manglea los nombres de los argumento
de las funciones. La alternativa es usar algo como [ngannotate-rails][5], o usar [otras formas de dependency injection
mas feas][6].
[1]: https://github.com/rharriso/bower-rails
[2]: https://github.com/moiristo/deep_cloneable
[3]: https://github.com/nathanl/searchlight
[4]: https://github.com/FineLinePrototyping/angularjs-rails-resource
[5]: https://github.com/kikonen/ngannotate-rails
[6]: https://docs.angularjs.org/guide/di
Content type
Image
Digest
Size
379.2 MB
Last updated
over 9 years ago
docker pull yavende/web