2013-05-17 3 views
6

Я пытался понять это весь день, и это сводит меня с ума.Rails pagination в API с использованием Her, Faraday

У меня есть два рельсовых приложения, ServerApp и ClientApp. ClientApp получает данные от ServerApp через API, используя ее драгоценный камень. Все было здорово, пока мне не понадобилась информация для разбивки на страницы.

Это метод я использую, чтобы получить заказы (это использует kamainari для пагинации и рыскать для поиска):

# ServerApp 
def search 
    @search = Order.includes(:documents, :client).order('id desc').search(params[:q]) 
    @orders = @search.result(distinct: true).page(params[:page]).per(params[:per]) 

    respond_with @orders.as_json(include: :documents) 
end 

Он возвращает массив хэш в JSON, который Ее использует в качестве коллекции заказы. Это прекрасно работает.

# Response 
[ 
    { 
    "client_id": 239, 
    "created_at": "2013-05-15T15:37:03-07:00", 
    "id": 2422, 
    "ordered_at": "2013-05-15T15:37:03-07:00", 
    "origin": "online", 
    "updated_at": "2013-05-15T15:37:03-07:00", 
    "documents": [ 
     { ... } 
    ] 
    }, 
    ... 
] 

Но мне нужна информация разбивки на страницы. Казалось, мне нужно было send it as metadata with my json. Так что я изменить свой ответ на этот вопрос:

respond_to do |format| 
    format.json do 
    render json: { orders: @orders.as_json(include: :documents), metadata: 'sent' } 
    end 
end 

Это действительно отправить через метаданные, так что в моей ClientApp я могу написать @ orders.metadata и получить «послал». Но теперь мои заказы вложены в массив внутри «заказов», поэтому мне нужно использовать @ orders.orders, а затем он рассматривает его как массив, а не ее коллекцию.

После некоторого чтения казалось, что передача информации разбивки на страницы с помощью заголовков была такой же, как и многие другие люди (я смог получить заголовки, настроенные в файле after_filter, используя this guide). Но я еще больше теряю информацию о том, как получить эти заголовки ответов в своем ClientApp - я считаю, что мне нужно промежуточное ПО Faraday, но мне просто нечего делать, чтобы это работало.

Если кто знает, как я могу это сделать, я был бы очень благодарен. Я не могу взять еще один день, ударяя головой о стену, но я чувствую, что я всего лишь один важный фрагмент информации из этого!

+0

ЭВТ. это также может быть проблемой для ее проекта. Вы можете открыть там проблему и посмотреть, есть ли у вас отзывы от разработчиков проекта. – poseid

+0

Я рассмотрел возможность публикации ее на странице ее github, но я подумал, что это было более непонимание с моей стороны, а не проблема с их стороны. – d3vkit

ответ

6

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

Вот код:

class CustomParserMiddleware < Her::Middleware::DefaultParseJSON 
     def parse(env) 
     json = parse_json(env[:body]) 
     pagination = parse_json(env[:response_headers][:pagination_key]) || {} 
     errors = json.delete(:errors) || {} 
     metadata = json.delete(:metadata) || {} 
     { 
      :data => json, 
      :errors => errors, 
      :metadata => { 
       :pagination => pagination, 
       :additional_metadata => metadata 
      }, 

    end 

     def on_complete(env) 
     env[:body] = case env[:status] 
      when 204 
      parse('{}') 
      else 
      parse(env) 
     end 
     end 
    end 

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

model = Model.all 
    model.metadata[:pagination] 
0
  • Вы можете передать параметры заголовка Фарадею при настройке соединения см документации на http://rubydoc.info/gems/faraday/0.8.7/Faraday/Connection:initialize

  • Иногда это помогает сделать запрос curl первым, особами. используйте опцию -vv для подробного вывода, где вы увидите все заголовки. (Возможно, вы также можете подключить некоторые логические выходы с сервера)

  • Вы можете использовать, например. clogger (http://clogger.rubyforge.org/) отслеживает информацию заголовка на стороне сервера Rails

+0

Я на самом деле уже добавляю заголовки в Faraday, используя промежуточное программное обеспечение, которое публикуется на ее странице github. Проблема в том, что я не совсем понимаю, как написать on_complete middleware, чтобы получить заголовки, отправленные обратно из API, а затем сделать их доступными для моего контроллера. И я использую расширение Postman Chrome, и заголовки там - я просто не уверен, как их использовать! Дальше я видел руководство, описывающее, что делать с заголовками, связанными с записью в журнал. – d3vkit

2

я, наконец, получил эту работу. Трюк состоял в том, чтобы использовать глобальную переменную в faraday on_complete - я попытался найти лучшее решение, но это было лучшее, что я мог сделать. Еще раз, я получил код заголовка от here. Вот полное руководство по работе с ней:

Во-первых, на моей стороне сервера у меня есть камень Kaminari, и я передаю page и per в качестве параметров на сервер от клиента.(Это также использует Ransack для поиска)

def search 
    @search = Order.order('id desc').search(params[:q]) 
    @orders = @search.result(distinct: true).page(params[:page]).per(params[:per]) 

    respond_with @orders.as_json(include: :items) 
end 

Мой клиент делает запрос следующим образом:

@orders = Order.search(q: { client_id_eq: @current_user.id }, page: params[:page], per: 3)` 

Назад на сервере, у меня есть это в моем ApiController (контроллер приложения для API):

protected 
    def self.set_pagination_headers(name, options = {}) 
    after_filter(options) do |controller| 
     results = instance_variable_get("@#{name}") 
     headers["X-Pagination"] = { 
     total_count: results.total_count, 
     offset_value: results.offset_value 
     }.to_json 
    end 
    end 

В orders_controller.rb сервера я установил заголовки нумерации страниц для метода поиска:

class OrdersController < ApiController 
    set_pagination_headers :orders, only: [:search] 
    ... 
end 

Теперь, чтобы получить заголовки, нам нужно промежуточное ПО Faraday в ней на клиенте.

# config/initializers/her.rb 
Her::API.setup url: Constants.api.url do |c| 
    c.use TokenAuthentication 
    c.use HeaderParser # <= This is my middleware for headers 
    c.use Faraday::Request::UrlEncoded 
    c.use Her::Middleware::DefaultParseJSON 
    c.use Faraday::Adapter::NetHttp 
    c.use Faraday::Response::RaiseError 
end 

# lib/header_parser.rb 
# don't forget to load this file in application.rb with something like: 
# config.autoload_paths += Dir[File.join(Rails.root, "lib", "*.rb")].each { |l| require l } 

class HeaderParser < Faraday::Response::Middleware 
    def on_complete(env) 
    unless env[:response_headers]['x-pagination'].nil? 
     # Set the global var for pagination 
     $pagination = JSON.parse(env[:response_headers]['x-pagination'], symbolize_names: true) 
    end 
    end 
end 

Теперь, на вашем клиентском контроллере, у вас есть глобальная переменная хэша, называемая $ pagination; мина выглядит следующим образом:

$pagintation = { total_count: 0, offset_value: 0 }` 

Наконец, я добавил Kaminari драгоценного камня к моему клиенту приложению для постраничного массива и получить эту простые нумерации страниц ссылки:

@orders = Kaminari.paginate_array(@orders, total_count: $pagination[:total_count]).page(params[:page]).per(params[:per_page])` 

Я надеюсь, что это может помочь кому-то еще, и если кто-нибудь знает лучший способ сделать это, дайте мне знать!

 Смежные вопросы

  • Нет связанных вопросов^_^