从Ember App调用嵌套的Rails路由

时间:2018-03-22 10:37:03

标签: ember.js ember-data rails-api

如果我不需要嵌套模板,如何从Ember应用程序调用嵌套的Rails路由? 我在Rails路由器中有以下路由:

# routes.rb
resources :shops do
  resources :shop_languages
end

因此,要获得商店语言列表,应该点击shops/:shop_id/shop_languages

这是ShopsLanguagesController:

# controllers/shop_languages_controller.rb
class ShopLanguagesController < ApplicationController
  before_action :find_shop

  def index
    json_response @shop.shop_languages, :ok, include: 'language'
  end

  private

    def find_shop
      @shop = Shop.find(params[:shop_id])
    end
end

在Ember应用程序中,我的路线定义如下:

# router.js
Router.map(function() {
...
  this.route('languages', { path: '/shops/:shop_id/shop_languages'});
});

在Ember application.hbs模板中,语言链接定义如下

# application.hbs
{{#link-to 'languages' currentUser.user.shop.id class="nav-link"}}
..
{{/link-to}}

在Ember languages.js路由处理程序中,我正在尝试加载商店语言:

# routes/languages.js
model(params) {
  return this.store.query('shop-language', { shop_id: params.shop_id })
}

Ember点击/shop-languages终点而不是嵌套的shops/:shop_id/shop_languages

当然,我已经在Ember方面定义了相应的模型:

# models/shop-language.js
import DS from 'ember-data';

export default DS.Model.extend({
  shop: DS.belongsTo('shop'),
  language: DS.belongsTo('language'),
  modified_by:  DS.attr('string')
});

这有什么问题以及如何使其发挥作用?谢谢

2 个答案:

答案 0 :(得分:3)

答案简短;对服务器的请求与您的路由结构不匹配,但是基于您的模型和您正在使用的适配器,例如REST与JSON API基于服务器上调用的URL可能不同。

因此,要将/shop/:id/添加为shop-language查询的前缀,您必须覆盖适配器的默认行为。

开始为您的模型生成适配器 ember g adapter shop-language

在新的适配器中,您可能必须覆盖2个功能

1)queryhttps://github.com/emberjs/data/blob/master/addon/adapters/rest.js#L549

2)urlForQueryhttps://github.com/emberjs/data/blob/master/addon/-private/adapters/build-url-mixin.js#L188

另请查看处理所有不同方案的buildURLhttps://github.com/emberjs/data/blob/master/addon/-private/adapters/build-url-mixin.js#L55)。

在1)您可能希望从查询参数中删除shop_id,这样您就不会得到像/shops/1/shop-languages?shop_id=1这样的网址

2)您必须根据传递的查询参数将/shops/1添加到您的网址

答案 1 :(得分:0)

感谢@dguettler,我找到了一个解决方案来实现它。

在灰烬方面

声明语言路由如下:

#router.js
Router.map(function() {
  this.route('languages', { path: 'shops/:shopId/languages'});
  ..
});

修改/创建languages.js路由处理程序,如下所示:

#routes/languages.js

import Route from '@ember/routing/route';
import AuthenticatedRouteMixin from 'ember-simple-auth/mixins/authenticated-route-mixin';

export default Route.extend(AuthenticatedRouteMixin, {
  model(params) {
    return this.store.query('shop-language', { shopId: params.shopId});
  }
});

创建/修改shop-language.js适配器,如下所示:

#adapters/shop-language.js

export default ApplicationAdapter.extend({
  urlForQuery (query) {
    return this._buildShopUrl(query.shop_id)
  },

urlForCreateRecord(modelName, snapshot) {
  return this._buildShopUrl(snapshot.belongsTo('shop').id);
},

urlForDeleteRecord(id, modelName, snapshot) {
  return this._buildShopUrl(snapshot.id, id);
},

_buildShopUrl(shop_id, id) {
  if (id) {
    return `shops/${shop_id}/languages/${id}`;
  }
  return `shops/${shop_id}/languages`;
 }
});

添加链接以将商店语言加载到您的模板:

#templates/application.hbs

...
{{#link-to 'languages' currentUser.user.shop.id class="nav-link"}}
...
{{/link-to}}

languages.hbs模板中显示商店语言:

#templates/languages.hbs

<ul class="list-group list-group-flush">
  {{#each model as |lang|}}
    <li class="list-group-item">{{lang.tag}}</li>
  {{/each}}
</ul>

在Rails API方面

将shop_languages资源声明为嵌套路由:

#routes.rb
...
resources :shops do
  resources :shop_languages, path: '/languages'
end

ShopLanguagesController中加载商店语言:

#controllers/shop_languages_controller.rb

class ShopLanguagesController < ApplicationController
  before_action :find_shop

  def index
    json_response @shop.languages, :ok
  end

  private

  def find_shop
    @shop = Shop.find(params[:shop_id])
  end
end

我有一件事要做 - 从网址中删除?shopId=613并修复包含一种双重值的params哈希:

Started GET "/shops/613/languages?shopId=613" for 127.0.0.1 at 2018-03-23 10:05:53 +0100
Processing by ShopLanguagesController#index as JSONAPI
  Parameters: {"shopId"=>"613", "shop_id"=>"613"}