Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Проект построен как вебсервис с rest интерфейсом. Клиентская и
- серверная части написаны полностью на java scriipt.
- Архитектура nodejs в связке с фреймворком express позволила обеспечить
- прозрачность работы над созданием rest интерфейса.
- Пример добавления метода к ресурсу.
- роут:
- app.get '/post',[
- $.beforeAction,
- $.controller('post').list
- ]
- Все операции связаныые с проверкой доступа и прочее, мы вынесли метод
- $.beforeAction, что бы избавить контроллеры от лишней логики
- метод контроллера
- class PostController
- list: (req, res) ->
- Post.find {}, (err, posts) ->
- res.send posts
- Так же в рамках разработки проекта была выполнена работа по созданию
- структурной надстройки над фреймворком express, которая позволила вынесить
- отедльные модули системв в независимые друг от друга приложения, это
- обеспечивает большую гибкость и простоту маштабирования в будущем.
- Для подключения новых модулей в файле app.coffee необходимо добавить путь
- к файлу-инициализатору нового подприложения.
- require('./frontend/configs/bootstrap').apply app
- По такому же принципу мы построили и механизм конфигурации приложения
- require('./configs/bootstrap').apply app
- require('./admin/configs/bootstrap').apply app
- в файлах дополнительных окружений можно просто переопределить некоторые
- параметры основго конфигрурационного скрипта.
- пример файла конфигурации
- exports.apply = (app)->
- app.configure 'production', ->
- app.use express.errorHandler {
- dumpExceptions: true,
- showStack: true
- }
- app.use express.session
- secret: "soundFree_secred_Wdi78"
- store: new MongoStore({
- db: new Db('soundFree_session',
- new Server('localhost', 27017,{
- auto_reconnect: true,
- native_parser: true
- })
- ,{}
- )
- })
- mongoose.connect('mongodb://localhost/soundFree', (err)->
- if err
- console.error 'Can not connect to database'
- throw err;
- console.info 'Successfully connected to database'
- )
- app.set 'port', 8000
- app.set 'view cache', false
- Для написания кода был использован coffeeScript, он обеспечивает возможность написания java script приложений на python/ruby подобном синтаксисе. Так же coffeeScript обеспечивает более прозрачную работу с ООП в java script.
- Пример:
- lass Animal
- constructor: (@name) ->
- move: (meters) ->
- alert @name + " moved #{meters}m."
- class Snake extends Animal
- move: ->
- alert "Slithering..."
- super 5
- class Horse extends Animal
- move: ->
- alert "Galloping..."
- super 45
- sam = new Snake "Sammy the Python"
- tom = new Horse "Tommy the Palomino"
- sam.move()
- tom.move()
- В качестве базы данных была использована mongoDB, это было обусловлненно тем что
- данная субд полностью асинхронна, что хорошо вписывается в общий характер проекта
- и поддерживает парадигмы ассинхронной природы nodejs который является основной системы.
- пример подключения к базе данных
- store: new MongoStore({
- db: new Db('soundFree_session',
- new Server('localhost', 27017,{
- auto_reconnect: true,
- native_parser: true
- })
- ,{}
- )
- })
- В качестве ORM обертки для MongoDB был использован mongoose
- конфигурация
- mongoose.connect('mongodb://localhost/soundFree', (err)->
- if err
- console.error 'Can not connect to database'
- throw err;
- console.info 'Successfully connected to database'
- )
- пример модели
- mongoose = require 'mongoose'
- Schema = mongoose.Schema
- Query = mongoose.Query
- ObjectId = Schema.ObjectId
- crypto = require 'crypto'
- UserSchema = new Schema
- name:
- type: String
- required: true
- email:
- type: String
- required: true
- unique: true
- set: (v)->
- toLower(v)
- password:
- type: String
- set: (v)->
- setPassword(v)
- salt:
- type: String
- role: String
- status: String
- createdAt:
- type: Date
- default: Date.now
- toLower = (v) ->
- v.toLowerCase()
- UserSchema.path('email').validate (email) ->
- return /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/.test email
- , 'invalid'
- setPassword = (v) ->
- v.length ? v: this.password
- UserSchema.pre 'save', (next) ->
- if !@salt
- if !@password
- @realPassword = crypto.randomBytes(4).toString 'hex'
- @password = @realPassword
- @generateSalt();
- @password = @hashPassword @password, @salt
- next()
- User = mongoose.model 'User', UserSchema
- global.User = User
- Внешний вид
- В качестве css фреймворка был выбран продукт Twitter Bootstrap, позволяющий быстро
- создавать прототипы приложений с дружественным пользовательским интерфейсом, весь
- css код написан на less синткасисе, который позволяет использвать в стилях вложенность, примеси, использовать переменные т.д
- пример
- @base: #f938ab;
- .box-shadow(@style, @c) when (iscolor(@c)) {
- box-shadow: @style @c;
- -webkit-box-shadow: @style @c;
- -moz-box-shadow: @style @c;
- }
- .box-shadow(@style, @alpha: 50%) when (isnumber(@alpha)) {
- .box-shadow(@style, rgba(0, 0, 0, @alpha));
- }
- .box {
- color: saturate(@base, 5%);
- border-color: lighten(@base, 30%);
- div { .box-shadow(0 0 5px, 30%) }
- }
- Организация клиентской части.
- Для организации интерфейса была использована библиотека backboneJS
- Данная библиотека позволяет использовать хеш навигацию с маппингом на методы роутера
- class Controller extends Backbone.Router
- routes:
- "" : "index"
- "!/": "index"
- "!/news": "news"
- "!/music": "music"
- "!/video": "video"
- "!/artists": "artists"
- "!/post/:id": "showPost"
- index: ->
- Views.page.render() if Views.page?
- news: ->
- console.log "news"
- music: ->
- console.log "music"
- video: ->
- console.log "videos"
- artists: ->
- console.log "artists"
- showPost: (id)->
- if Views.postPage?
- post = new Post {_id: id}
- Views.postPage.setModel post
- post.fetch()
- Блоки сайта отрисовываются на основе данных от моделей
- пример View
- class SitePage extends Backbone.View
- el: $ "#mainContainer"
- posts: []
- albums: []
- events: {}
- constructor: ->
- @posts = new PostCollection()
- @posts.bind 'add', @addPost, @
- @posts.bind 'all', @addAllPosts, @
- @albums = new AlbumCollection()
- @albums.bind 'add', @addAlbum, @
- @albums.bind 'all', @addAllAlbums, @
- render: ->
- @posts.fetch()
- @albums.fetch()
- $(@el).empty()
- $(@el).append(_.template $('#NewsContainer').html()) if !$(@el).find('#NewsContainer').length
- $(@el).append(_.template $('#AlbumContainer').html()) if !$(@el).find('#AlbumContainer').length
- addPost: (post)->
- view = new PostView
- model: post
- container = $(@el).find('.news')
- container.append view.render().el
- addAllPosts: ->
- @posts.each @addPost, @
- addAlbum: (album)->
- view = new AlbumView
- model: album
- container = $(@el).find('.albums')
- container.append view.render().el
- addAllAlbums: ->
- @albums.each @addAlbum, @
- Пример модели
- class Post extends Backbone.Model
- urlRoot : '/post/'
- url: ->
- @urlRoot + @get('_id')
- Взаимодействие между views и models построенно на основе событий, которые пораждает модель, которые в свою очередь могут быть перехвачены view.
Add Comment
Please, Sign In to add comment