Строим блог на Areto фреймворк

Контроллер фотографий

Класс PhotoController определяет контроллер модели фото.

module/admin/controllers/PhotoController.js

const Base = require('../component/CrudController');
module.exports = class PhotoController extends Base {

  static getConstants () {
    return {
      METHODS: {
        'assign-main': ['post']
      }
    };
  }
};
module.exports.init(module);
const async = require('areto/helper/AsyncHelper');
const Article = require('../model/Article');
const File = require('../model/File');
const Photo = require('../model/Photo');
Создание фото

Метод actionCreate создает модель фотографии. Массив асинхронных методов async.series получает данные для списка выбора статьи Article.findToSelect, к которой может быть привязано фото.

module/admin/controllers/PhotoController.js

actionCreate () {
  let model = new Photo;
  model.scenario = 'create';
  async.waterfall([
    cb => async.series({
      articles: cb => Article.findToSelect().all(cb)
    }, cb),
    (params, cb)=> {
      params.model = model;
      if (this.isGet()) {
        return this.render('create', params);
      }
      async.series([
        cb => model.load(this.getBodyParams()).save(cb),
        cb => model.isNew()
          ? this.render('create', params)
          : this.backToRef()
      ], cb);
    }
  ], err => this.throwError(err));
}
Просмотр загруженного фото

Метод actionView вызывает родительский метод для загрузки необходимых отношений.

module/admin/controllers/PhotoController.js

actionView () {
  super.actionView({
    with: ['article']
  });
}
Редактирование фото

Метод actionUpload сохраняет загруженный файл на сервер. Если файл проходит проверку, то из него создается модель фотографии, не привязанная к статье.

module/admin/controllers/PhotoController.js

actionUpload () {
  let file = new File, photo;
  async.series([
    cb => file.upload(this, cb),
    cb => file.hasError()
      ? this.sendText(this.translate(file.getFirstError()), 400)
      : cb(),
    cb => {
      photo = new Photo;
      photo.set('file', file.getId());
      photo.validate(cb, ['file']);
    },
    cb => photo.hasError()
      ? this.sendText(this.translate(photo.getFirstError()), 400)
      : this.sendText(file.getId())
  ], err => this.throwError(err));
}

Метод actionAssignMain устанавливает фото как главное в статье. Сохранение статьи осуществляется через метод forceSave, который не производит валидацию модели. Если у фотографии нет связанной статьи, то устанавливается flash-сообщение об ощибке (одноразовое сообщение в пользовательской сессии) и идет переадресация на страницу просмотра фото.

module/admin/controllers/PhotoController.js

actionAssignMain () {
  this.getModel({
    with: ['article']
  }, model => {
    let article = model.get('article');
    if (!article) {
      this.setFlash('danger', 'Article not found');
      return this.redirect(['view', model]);
    }
    article.set('mainPhotoId', model.getId());
    async.series([
      cb => article.forceSave(cb),
      cb => this.redirect(['article/view', article])
    ], err => this.throwError(err));
  });
}