Магистральная модель без коллекции.Отправка дубликатов данных на сервер? - PullRequest
7 голосов
/ 11 сентября 2011

У меня есть приложение Backbone, работающее на основе рельсов. У меня есть ресурс Invitation, и я могу отправить приглашения, отправив запрос POST в действие create контроллера приглашения.

Моя модель Backbone выглядит следующим образом (coffeescript):

class Invitation extends Backbone.Model
  urlRoot: '/invitations'

А шаблон для формы для отправки приглашения следует. Я попытался сделать его максимально приближенным к обычным формам рельсов, так как кажется, что Rails справится с этим лучше всего:

<form action="/invitations" accept-charset="UTF-8" id="new_invitation" class="new_invitation" method="post">
  <input id="invitation_recipient_name" class="invitation_recipient_name" type="text" name="invitation[recipient_name]" />
  <input id="invitation_recipient_email" class="invitation_recipient_email" type="text" name="invitation[recipient_email]" />
  <input type="submit" class="btn primary" name="commit" id="invite" value="Send Invitation" />
</form>

Вот мой Backbone View для этой модели и шаблона

class InvitationView extends Backbone.View
  # this is the template shown above
  template: JST['backbone/templates/invitation']
  events:
    'click #invite': 'sendInvite'

  render: ->
    $(this.el).html this.template()
    this
  sendInvite: (e) ->
    e.preventDefault()
    name = this.$('#invitation_recipient_name')
    email = this.$('#invitation_recipient_email')
    this.model.save
      recipient_name: name.val()
      recipient_email: email.val()

Проблема в том, что когда я нажимаю кнопку отправки и вызывается метод sendInvite, мой сервер получает данные со следующей структурой:

Parameters: {"recipient_name"=>"A name", "recipient_email"=>"name@example.com", "invitation"=>{"recipient_email"=>"name@example.com", "recipient_name"=>"A name"}}

Теперь это действительно работает, поскольку мое действие invitations#create предполагает работу с параметрами вида: params[:invitations], это стандарт для рельсов. Однако тот факт, что имя и электронная почта отправляются в запросе дважды, кажется признаком того, что что-то не так с моей настройкой.

Я что-то не так делаю или это правильно?

Вот мое действие контроллера, если кто-то хочет его увидеть:

  # POST /invitations
  def create
    @invitation = current_user.sent_invitations.new params[:invitation]

    respond_to do |format|
      if @invitation.save
        format.json { render_for_api :invitation, json: @invitation, status: :created }
      else
        format.json { render json: @invitation.errors, status: :unproccessible_entity }
      end
    end
  end

Редактировать Вот так выглядит моя модель приглашений, если я задаю атрибуты и регистрирую ее непосредственно перед сохранением:

  Invitation
    _changed: false
    _changing: false
    _escapedAttributes: Object
      __proto__: Object
    _previousAttributes: Object
      recipient_email: "dave@example.com"
      recipient_name: "Dave"
      __proto__: Object
    attributes: Object
      recipient_email: "dave@example.com"
      recipient_name: "Dave"
      __proto__: Object
    cid: "c17"
    __proto__: ctor

Этот журнал создается следующим кодом:

sendInvite: (e) ->
    e.preventDefault()
    name = @$('#invitation_recipient_name')
    email = @$('#invitation_recipient_email')
    @model.set recipient_name: name.val(), recipient_email: email.val()
    console.log "THe model to save", @model

Редактировать 2
Вот как я создаю свою точку зрения в роутере. Как мне изменить это так, чтобы Backbone автоматически отслеживал атрибуты моих моделей, даже если я не получаю и не устанавливаю их с сервера?.

  var TeamRouter = Backbone.Router.extend({
    routes: {
      'members': 'members'
    },

    members: function() {
      @invite = new MoveOutOrg.Models.Invitation();
      @inviteView = new MoveOutOrg.Views.InvitationView({
        model: @invite
      });
      $('#stage').append(@inviteView.render().el);
    }
  });

Ответы [ 3 ]

2 голосов
/ 16 сентября 2011

Поля params[:recipient_name] и params[:recipient_email] являются результатом вашего вызова на model.save(). Переданные параметры являются необязательными. Вам не нужно ничего передавать для сохранения, если модель уже создана с правильными значениями. Недостающий фрагмент - это то, как вы создали экземпляр представления.

Также я бы изменил событие на "submit #new_invitation". Это более наглядно. Вы заботитесь о том, чтобы форма была отправлена ​​... а не о том, что они нажали кнопку. Он также обнаруживает случай, когда они отправляют форму, не нажимая кнопку (например, нажав Enter).

Чтобы связать вид с моделью, используйте метод initialize.

initialize: ->
  @model.bind('change', @render)

Основное, что нужно помнить, это то, что model события всплывают в коллекциях и для всех, кто слушает. Так что теперь при сохранении, если какое-либо из свойств было изменено, сработает событие change, которое затем вызовет повторную визуализацию представления.

1 голос
/ 21 июня 2012

Причина, по которой данные дублировались в параметрах, связана с тем, что в Rails по умолчанию включен параметр ActiveSupport.wrap_parameters для запросов JSON.Проверьте /config/initializers/wrap_parameters.rb в своем проекте Rails.

Вы можете отключить его, изменив:

ActiveSupport.on_load(:action_controller) do
  wrap_parameters format: [:json]
end

на

ActiveSupport.on_load(:action_controller) do
  wrap_parameters format: []
end

Для получения дополнительной информации: http://guides.rubyonrails.org/action_controller_overview.html#parameters

0 голосов
/ 04 апреля 2012

Я недавно решил попробовать backbone.js с гемом backbone-rails и столкнулся с этой проблемой.Решение состоит в том, чтобы установить опцию paramRoot в модели:

class Invitation extends Backbone.Model
  urlRoot: '/invitations'
  paramRoot: 'invitation'

В codebrew по какой-то причине они не упоминаются в файле readme, но этот параметр включен в генераторы, которыепредоставляются.

...