Article model

The Article class is a article model. Also it integrates other entities of the blog.

Article view

The ATTRS property is not declared in the model of public section. because all article's changes will be made in the admin module. Add the name of table and string status IDs to the constants of class:

  • draft - article is in edit mode and is not available in the public section of blog.
  • published - article is available for viewing in the public section.
  • archived - article withdrawn from publication.

model/Article.js

const Base = require('areto/db/ActiveRecord');

module.exports = class Article extends Base {

  static getConstants () {
    return {
      TABLE: 'article',
      STATUS_DRAFT: 'draft',
      STATUS_PUBLISHED: 'published',
      STATUS_ARCHIVED: 'archived'
    };
  }
  // place methods here
};
module.exports.init(module);

const Comment = require('./Comment');
const Photo = require('./Photo');
const User = require('./User');
const Tag = require('./Tag');

Model title corresponds to the article title.

model/Article.js

getTitle () {
  return this.get('title');
}

The following methods are required to check status.

model/Article.js

isDraft () {
  return this.get('status') === this.STATUS_DRAFT;
}

isPublished () {
  return this.get('status') === this.STATUS_PUBLISHED;
}

isArchived () {
  return this.get('status') === this.STATUS_ARCHIVED;
}

Data query

The findPublished method returns a query that looks for all published articles. Also data for the mainPhoto, tags relations (see below) will be requested for each article.

model/Article.js

findPublished () {
  return this.find().and({status: this.STATUS_PUBLISHED}).with('mainPhoto','tags');
}

The findBySearch method extends the findPublished query. A filter is used to search for specific text in article titles.

model/Article.js

findBySearch (text) {
  const query = this.findPublished();
  if (typeof text === 'string' && /[a-z0-9\-\s]{1,32}/i.test(text)) {
    query.and(['LIKE', 'title', `%${text}%`]);
  }
  return query;
}

Model's relations

Methods prefixed by rel define the relations of the target model to others. Each relation is set via a link that is described in the return areto/db/ActiveQuery query.

The relAuthor method finds the article author. The hasOne, hasMany functions reflect a expected number of results. In this case, one article can have one author only.

The first argument (User) defines the model class associated with article. The second argument [User.PK, 'authorId'] contains attributes that form links. A primary key (User.PK) is used by user model. The authorId attribute that stores the identity of author is used by article.

model/Article.js

relAuthor () {
  return this.hasOne(User, User.PK, 'authorId');
}

The relPhotos method returns a query for all photos associated with article. Article may have a lot of photos, so hasMany method is used.

model/Article.js

relPhotos () {
  return this.hasMany(Photo, 'articleId', this.PK);
}

The main photo displayed in a list of articles defined in the relMainPhoto relation. The Article class contains the mainPhotoId attribute that keeps a model ID of the Photo class.

model/Article.js

relMainPhoto () {
  return this.hasOne(Photo, Photo.PK, 'mainPhotoId');
}

The relComments method defines comments, related to the article. Additional filter by status allows only approved ones for the public section of the blog.

model/Article.js

relComments () {
  return this.hasMany(Comment, 'articleId', this.PK).and({
    status: Comment.STATUS_APPROVED
  });
}

The relTags method selects tags relating to article. Each tag can be associated with multiple articles and each article can contain multiple tags. This type of relations is called a "many to many". It uses a junction table (rel_article_tag).

Link the Tag model with the junction table tagId field. The first argument of viaTable contains the name of junction table. The second argument binds the table articleId field to the Article model.

model/Article.js

relTags () {
  return this.hasMany(Tag, Tag.PK, 'tagId').viaTable('rel_article_tag', 'articleId', this.PK);
}