我今天在我的调试参数中注意到,获取时单个Backbone模型正在点击索引操作而不是Show操作。
My Backbone Marionette应用程序从索引视图开始:
index.html.erb
<div id="wrap">
<div id="header-region"></div>
<div id="main-region"></div>
<div id="push"></div>
</div>
<div id="footer-region"></div>
<div id="dialog-region"></div>
<%= javascript_tag do %>
$(function() {
SampleApp.start({
environment: "<%= Rails.env %>"
});
});
<% end %>
因为它在索引视图中运行,所以任何提取调用总是会在控制器的索引操作上解析吗?有没有办法可以强制主干模型获取调用来命中控制器的Show动作而不是索引动作?
奇怪的是网络调用在响应中显示/posts/17.json而不是/posts.json我希望在索引视图中看到。然而实际的呼叫似乎正在触及控制器中的索引动作。
编辑:
Approuter:
@SampleApp.module "SurveysApp", (SurveysApp, App, Backbone, Marionette, $, _) ->
class SurveysApp.Router extends Marionette.AppRouter
appRoutes:
"" : "list"
":id" : "show"
":id/take": "take"
API =
list: ->
new SurveysApp.List.Controller
show: (id, survey) ->
new SurveysApp.Show.Controller
id: id
survey: survey
take: (id, survey) ->
new SurveysApp.Take.Controller
id: id
survey: survey
newSurvey: (surveys) ->
new SurveysApp.New.Controller
surveys: surveys
App.vent.on "survey:clicked", (survey) ->
App.navigate "/" + survey.id
API.show survey.id, survey
App.vent.on "new:survey", (surveys) ->
API.newSurvey surveys
App.vent.on "take:survey:button:clicked", (survey) ->
App.navigate "/" + survey.id + "/take"
API.take survey.id, survey
App.vent.on "survey:list", ->
App.navigate "/"
API.list()
App.addInitializer ->
new SurveysApp.Router
controller: API
型号:
@SampleApp.module "Entities", (Entities, App, Backbone, Marionette, $, _) ->
class Entities.Survey extends App.Entities.Model
urlRoot: "surveys"
url: ->
if @.get('take') == true
url = @urlRoot + "/" + @id + "/fetch.json"
else
url = @urlRoot + "/" + @id + ".json"
return url
sync: (method, model, options) ->
@mySyncFunction method, model, options
mySyncFunction: (method, model, options) ->
if (method == 'GET')
options.url = model.url
else
options.url = @urlRoot + "/" + @id + ".json"
return Backbone.sync(method, model, options)
defaults:
status: "Draft"
number_taken: 0
survey_limit: 500
take: false
relations: [
type: Backbone.HasMany
key: "questions"
relatedModel: Entities.Question
reverseRelation:
key: 'survey'
includeInJSON: 'id'
]
扩展了这个:
@SampleApp.module "Entities", (Entities, App, Backbone, Marionette, $, _) ->
class Entities.Model extends Backbone.RelationalModel
initialize: ->
@listenTo(@, 'change', @modelChanged)
modelChanged: ->
@hasChangedSinceLastSync = true
sync: (method, model, options) ->
options = options || {}
success = options.success
options.success = (resp) ->
success && success(resp)
model.hasChangedSinceLastSync = false
super method, model, options
destroy: (options = {}) ->
_.defaults options,
wait: true
@set _destroy: true
super options
isDestroyed: ->
@get "_destroy"
save: (data, options = {}) ->
isNew = @isNew()
_.defaults options,
wait: true
success: _.bind(@saveSuccess, @, isNew, options.collection, options.callback)
error: _.bind(@saveError, @)
@unset "_errors"
super data, options
saveSuccess: (isNew, collection, callback) =>
if isNew ## model is being created
collection?.add @
collection?.trigger "model:created", @
@trigger "created", @
else ## model is being updated
collection ?= @collection ## if model has collection property defined, use that if no collection option exists
collection?.trigger "model:updated", @
@trigger "updated", @
callback?()
saveError: (model, xhr, options) =>
## set errors directly on the model unless status returned was 500 or 404
@set _errors: $.parseJSON(xhr.responseText)?.errors unless /500|404/.test xhr.status
API =
newModel: (attrs) ->
new Entities.Model attrs
App.reqres.setHandler "new:model", (attrs = {}) ->
API.newModel attrs
控制器:
class SurveysController < ApplicationController
before_action :set_survey, only: [:show, :fetch, :edit, :update, :destroy]
# GET /surveys
# GET /surveys.json
def index
unless signed_in?
redirect_to signin_path
end
@surveys = Survey.where(user_id: cookies[:theoremreach_user_id])
end
# GET /surveys/1
# GET /surveys/1.json
def show
respond_to do |format|
format.json
format.csv { send_data @survey.to_csv }
format.xls #{ send_data @survey.to_csv(col_sep: "\t") }
end
end
def fetch
unless signed_in?
redirect_to signin_path
end
respond_to do |format|
format.json
end
end
# GET /surveys/new
def new
@survey = Survey.new
end
# GET /surveys/1/edit
def edit
# unless signed_in?
# redirect_to signin_path
# end
end
# POST /surveys
# POST /surveys.json
def create
@survey = Survey.new(survey_params)
respond_to do |format|
if @survey.save
if @survey.status == "Submitted"
SurveyMailer.survey_created(@survey).deliver
end
format.html { redirect_to @survey, notice: 'Survey was successfully created.' }
format.json { render action: 'show', status: :created, location: @survey }
else
format.html { render action: 'new' }
format.json { render json: @survey.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /surveys/1
# PATCH/PUT /surveys/1.json
def update
respond_to do |format|
if @survey.update(survey_params)
if @survey.status == "Submitted"
SurveyMailer.survey_created(@survey).deliver
end
format.html { redirect_to @survey, notice: 'Survey was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: @survey.errors, status: :unprocessable_entity }
end
end
end
# DELETE /surveys/1
# DELETE /surveys/1.json
def destroy
@survey.destroy
respond_to do |format|
format.html { redirect_to surveys_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_survey
@survey = Survey.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def survey_params
params.require(:survey).permit(:number_taken, :survey_limit, :title, :status, :user_id)
end
end
routes.rb中:
resources :surveys
resources :surveys do
get :fetch, on: :member
end
基本上我正在尝试做的目标是让surveys#1/take
点击控制器中的Show动作,不需要用户登录(任何人都应该能够进行调查) ),而调查/ 1或调查索引应分别点击获取/索引操作并需要登录(在编辑/查看调查列表之前/之后)。
现在,调查#1 / take route正在点击控制器上的Index操作,并要求用户登录。