Meteor. Как же запилить этот ваш iron:router для CRUD?

  • Tutorial
Элементарно! Но если бы мне показали подобную инструкцию раньше…

Задание


По запросу /profile без ключа отдаю шаблон login, если пользователь «не того», иначе отдаю шаблон на добавление newProfile или редактирование profile (editMode) своего профиля. А по запросу /profile/key отдаю шаблон на просмотр profile (not editMode) любого профиля; при этом userId не светится, и неверные ключи отвергаются на invalidProfile.

[исходник]

Решение


Создаю коллекцию.
@Collections.Profiles = new Mongo.Collection('profiles')

Карта роутера (путь-название).
Router.route '/profile/:_id?', 
  name: 'profile'

Создаю роутер.
@ProfileController = RouteController.extend

Переменная с искомыми данными (нужна для передачи между двумя методами роутера).
  profile: null

Роутер будет ожидать объявленные подписки.
  waitOn: ->

Магия — реактивность.
    if Meteor.loggingIn()
      # First, because twice exec. It is reactivity: http://docs.meteor.com/#/full/reactivity
      # https://github.com/EventedMind/iron-router/blob/devel/Guide.md#reactivity

Если в URL есть параметр, то подписка на просмотр коллекции.
    else if @params._id
      return Meteor.subscribe 'profile4view', @params._id

Иначе если пользователь залогинен, то подписка на редактирование коллекции.
    else if Meteor.userId()
      return Meteor.subscribe 'profile4edit', Meteor.userId()

Обработка запроса к роутеру: получаю данные из коллекции и выбираю шаблон.
  action: ->
    @profile = null
    if Meteor.loggingIn()
      @template = 'wait'
    else if @params._id
      @profile = Collections.Profiles.findOne 
        _id: @params._id
      if @profile
        @template = 'profile'
      else
        @template = 'invalidProfile'
    else if Meteor.userId()
      @profile = Collections.Profiles.findOne 
        userId: Meteor.userId()
      if @profile
        @template = 'profile'
      else
        @template = 'newProfile'
    else
      @template = 'login'
    @render()

Передаю данные в шаблон на рендеринг.
  data: ->
    if not @profile
      return
    result = 
      editMode: not @params._id
      profile: @profile
    return result

Публикация подписок.
Meteor.publish 'profile4edit', (userId) ->
  check(arguments, [Match.Any])
  [
    Collections.Profiles.find
      userId: userId
  ]
Meteor.publish 'profile4view', (id) ->
  check(arguments, [Match.Any])
  [
    Collections.Profiles.find
      _id: id
    ,
      fields:
        userId: 0
  ]

Правила доступа для коллекции.
@Collections.Profiles.allow
  insert: (userId, doc) ->
    userId and doc and userId is doc.userId
  update: (userId, doc, fieldNames, modifier) ->
    userId and doc and userId is doc.userId
  # remove: (userId, doc) ->
  #   userId and doc and userId is doc.userId
  fetch: ['userId']


PS Удаление не реализовано. Дедушка учил, что не надо ничего выкидывать, в хозяйстве все пригодится.

PSS Веселюсь на Метеоре с момента выхода релиза 1.0, настойчиво рекомендую. Несколько открытых проектов: браузерная игрушка, новостная лента, генератор форм, фреймворк для мобильников, интернет-магазин для мобильников, тудушечка, клон Trello, доска объявлений, учебник для челябинцев. Новости про Метеор на crater.io.
Поделиться публикацией

Комментарии 18

    +2
    Что-то я не всё понял…
    Откуда взялась коллекция Profiles? Да и для чего она вообще, если у каждого пользователя есть свой profile?
    Зачем делать две публикации на просмотр и редактирование, когда они предоставляют одни и те же данные? Почему отдаются все поля записи, там же может быть что-то не для всех глаз… И чем key отличается от _id, который якобы скрыт? Плюс пользователю всегда публикуется его users.profile и он его может менять… ну и, собственно, вопрос: где CRUD? (-:
      +1
      Откуда взялась коллекция Profiles?
      Из первой строки кода.
      Да и для чего она вообще, если у каждого пользователя есть свой profile?
      Потребовалось вынести в отдельную коллекцию. Но не суть, это для примера.
      Зачем делать две публикации на просмотр и редактирование, когда они предоставляют одни и те же данные?
      Разные параметры: userId и profile._id
      Почему отдаются все поля записи, там же может быть что-то не для всех глаз…
      Прятать можно — fetch.
      И чем key отличается от _id,
      Нарасовал key для обозначения значения параметра.
      который якобы скрыт?
      При редактировании оперируем с userId, а при просмотре только с profile._id
      где CRUD? (-:
      Понимаю, что нужно рассказать про AutoForm.
        0
        AutoForm мне сорвал башню, маленько настругал.
          0
          Настругайте ещё selectpicker, а то меня ломает ((((-:
            0
            Selectize — the best of the best of the best! Forever.
              0
              Как firstOption сделать реактивной?
                0
                Засунуть в autorun. Еще есть ReactiveVar.
                  0
                  Вот этот гембель для простой смены надписи и расстраивает в автоформе…
                    0
                    Так оно же безотносительно AutoForm.
          0
          Про автоформ не надо рассказывать, и так известно (-:
          Лучше расскажите про локализацию автоформы… как нормально сделать реактивными сообщения, label, опции и т.п. Или, никак не догоняю, как на autoform-bs-datepicker навесить ивенты? Где их писать?
          Вопрос в том, что CRUD подразумевает некоторые действия, это же аббревиатура из глаголов, а, собственно, ни одного из действий глаголов в статье нет.
          Вопрос про коллекцию был не про «первую строчку», а о том, что была изменена, по-видимому, логика операций с пользователями и теперь у пользователей есть user.profile, а так же ещё одна сущность коллекция для того же — вот это мне не понятно.
          Теперь понял про key и user._id. Ну если Вам так удобно… мне не понятно, ну да ладно… но опять-таки, а где Вы храните информацию от accounts-? В коллекции или в пользователе?
          Прятать нужно не в fetch, а в fields публикации.
            0
            Про автоформ не надо рассказывать, и так известно (-:
            Лучше расскажите про локализацию автоформы… как нормально сделать реактивными сообщения, label, опции и т.п. Или, никак не догоняю, как на autoform-bs-datepicker навесить ивенты? Где их писать?
            Да хрен его знает, товарищ майор. До локализации AutoForm еще не добрался. Есть задел, для useraccounts оно работало. За autoform-bs-datepicker могу сказать, что обернул v4beta — это счастье. А что не так с ивентами? На шаблон страницы можно навесить, например.

            Вопрос в том, что CRUD подразумевает некоторые действия, это же аббревиатура из глаголов, а, собственно, ни одного из действий глаголов в статье нет.
            В заголовке же «для CRUD».

            Вопрос про коллекцию был не про «первую строчку», а о том, что была изменена, по-видимому, логика операций с пользователями и теперь у пользователей есть user.profile, а так же ещё одна сущность коллекция для того же — вот это мне не понятно.
            Если не назначить явно options.profile для Accounts.createUser, то и нет его в db.users.

            Вы храните информацию от accounts-? В коллекции или в пользователе?
            Я не вмешиваюсь в действия пакетов «accounts-». Если они задействуют db.users.profile — это их забота. В коллекции profiles анкеты пользователей (т.е. данные сами набивают). Вопрос в названии коллекции. Неважно.

            Прятать нужно не в fetch, а в fields публикации.
            И там тоже. Сам себе ответил.
              0
              Мне ивент нужен не на шаблон, а на изменение даты в одном пикере, чтобы установить мин/макс дату в другом пикере… ивент on()
                0
                спрятал userId в profile4view
                0
                Лучше расскажите про локализацию автоформы… как нормально сделать реактивными сообщения, label, опции и т.п.

                autoform-i18n


                нашёл недавно :)

            0
            Уже давно не Meteor.Collections, а Mongo.Collections. Router.map желательно не использовать, так как велика вероятность, что его уберут в последующих версиях iron-router.
              0
              Спасибо, подправил.
              0
              Добавил обработку Meteor.loggingIn()
                0
                Подправил обработку this.ready()

                Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                Самое читаемое