JSONApi part1

This commit is contained in:
2015-09-02 15:52:48 +02:00
parent 5d1ecd81c8
commit f47a8a9ed0
51 changed files with 386 additions and 141 deletions
+1 -1
View File
@@ -15,7 +15,7 @@ gem 'slim-rails'
# Gems used only for assets and not required
# in production environments by default.
gem 'active_model_serializers', '~> 0.9.3' # explicitly outside assets
gem 'active_model_serializers', '~> 0.10.0.rc2' # explicitly outside assets
group :assets do
gem 'jquery-rails'
gem 'jquery-ui-rails'
+4 -4
View File
@@ -67,8 +67,8 @@ GEM
activemodel (>= 3.0.2, < 5.0)
activesupport (>= 3.0.2, < 5.0)
active_decorator (0.5.3)
active_model_serializers (0.9.3)
activemodel (>= 3.2)
active_model_serializers (0.10.0.rc2)
activemodel (>= 4.0)
activejob (4.2.4)
activesupport (= 4.2.4)
globalid (>= 0.3.0)
@@ -236,7 +236,7 @@ GEM
http_parser.rb (0.6.0)
i18n (0.7.0)
iso_country_codes (0.7.1)
jquery-rails (4.0.4)
jquery-rails (4.0.5)
rails-dom-testing (~> 1.0)
railties (>= 4.2.0)
thor (>= 0.14, < 2.0)
@@ -465,7 +465,7 @@ DEPENDENCIES
ace-rails-ap
active_attr
active_decorator
active_model_serializers (~> 0.9.3)
active_model_serializers (~> 0.10.0.rc2)
airbrussh
bourbon
cancancan
@@ -1,4 +1,4 @@
App.ListsIndexEntryComponent = Ember.Component.extend
App.ListIndexEntryComponent = Ember.Component.extend
layoutName: 'lists/index-entry'
classNames: ['lists-overview-entry']
classNameBindings: ['content.active:active']
@@ -4,7 +4,7 @@ App.MenuItemProductOrdersComponent = Ember.Component.extend
layoutName: 'components/menu/product_orders'
classNames: ['menu-list-item', 'menu-list-item-product-orders']
classNameBindings: ['product_orders.length:show:hide', 'currentRoute:active']
currentRoute: (-> @get('targetObject.currentRouteName') is 'product_orders' ).property('targetObject.currentRouteName')
currentRoute: Ember.computed.equal 'targetObject.currentPath', 'product-orders'
orderTotals: Ember.computed.mapBy 'product_orders', 'total'
orderTotal: Ember.computed.sum 'orderTotals'
#orderTotal: Ember.computed 'product_orders.@each.total', ->
@@ -2,9 +2,9 @@ App.MenuItemListNeedsHelpComponent = Ember.Component.extend Ember.ViewTargetActi
action: 'listNeedsHelp'
layoutName: "components/menu/list_needs_help"
classNames: 'menu-list-item callout'
classNameBindings: ['globals.list.needs_help:active']
classNameBindings: ['globals.active_list.needs_help:active']
click: ->
if @get('globals.list.needs_help')
if @get('globals.active_list.needs_help')
@set 'globals.notice', t('list_needs_help.help_is_on_its_way')
else
@triggerAction()
@@ -2,9 +2,9 @@ App.MenuItemListNeedsPaymentComponent = Ember.Component.extend Ember.ViewTargetA
action: 'listNeedsPayment'
layoutName: "components/menu/list_needs_payment"
classNames: 'menu-list-item callout'
classNameBindings: ['controller.list.needs_payment:active']
classNameBindings: ['globals.active_list.needs_payment:active']
click: ->
if @get('controller.list.needs_payment')
if @get('globals.active_list.needs_payment')
@set 'globals.notice', t('list_needs_payment.payment_already_requested')
else
@triggerAction() #action: 'listNeedsPayment'
@@ -14,14 +14,14 @@ App.NewProductOrdersListComponent = Ember.Component.extend
# @get('product_orders').invoke 'eraseRecord'
orderProducts: ->
# table = @get('controllers.table.model')
# list = @get('globals.list')
# list = @get('globals.active_list')
# order = @store.createRecord('order', list: list, table: table)
# new_product_orders = @store.all('product_order').filterProperty('order', null)
# order.get('product_orders').pushObjects(new_product_orders)
#
# order.save().then (response)=>
# new_product_orders.invoke 'eraseRecord'
# if @get('globals.list')
# if @get('globals.active_list')
# @transitionToRoute 'active_list'
# else
# # Get list info from the server
@@ -2,4 +2,4 @@ App.ActiveListController = Ember.Controller.extend
#orders: (->
#@get('list.orders')
#).property('list.orders')
list: (-> @get('globals.list') ).property('globals.list')
list: Ember.computed.alias 'globals.active_list'
@@ -1,5 +1,4 @@
App.ApplicationController = Ember.Controller.extend
#list: Ember.computed.alias 'globals.list'
#notice: ''
actions:
confirmCancel: ->
@@ -10,7 +9,7 @@ App.ApplicationController = Ember.Controller.extend
@set 'globals.notice', ''
showSupplierStatusInfo: ->
@modal 'supplier_status_info',
model: @get('globals.list.supplier')
model: @get('globals.active_list.supplier')
title_path: 'supplier_status_info.title'
openDebugger: ->
@@ -21,14 +20,14 @@ App.ApplicationController = Ember.Controller.extend
).observes('currentPath')
events:
notify: (notification) -> @set 'globals.notice', notification.message
list_helped: -> @set 'globals.list.needs_help', false
list_needs_help: -> @set 'globals.list.needs_help', true # incoming from other users
list_is_paid: -> @set 'globals.list.needs_payment', false
list_needs_payment: -> @set 'globals.list.needs_payment', true # incoming from other users
list_helped: -> @set 'globals.active_list.needs_help', false
list_needs_help: -> @set 'globals.active_list.needs_help', true # incoming from other users
list_is_paid: -> @set 'globals.active_list.needs_payment', false
list_needs_payment: -> @set 'globals.active_list.needs_payment', true # incoming from other users
list_closed: (data)->
@transitionToRoute('list', data.id).then =>
@set 'globals.list.state', 'closed'
@set 'globals.list', null
@set 'globals.active_list.state', 'closed'
@set 'globals.active_list', null
order_being_processed: (data)->
order = @store.all('order').findBy 'id', data.id
order.set('state', 'active') if order
@@ -65,7 +64,7 @@ App.ApplicationController = Ember.Controller.extend
join_request_approved: (data)->
return @transitionToRoute 'active_list' if @get('globals.list.id') # Not interested when there is an active list
return @transitionToRoute 'active_list' if @get('globals.active_list.id') # Not interested when there is an active list
# The rest of the code is for the new user
@setCurrentList ->
@transitionToRoute('active_list').then =>
@@ -73,16 +72,16 @@ App.ApplicationController = Ember.Controller.extend
@set 'globals.join_request_sent', false
list_changed_table: (data)->
@store.findRecord('table', data.to_table_id).then (table)=>@set('globals.list.table', table)
@store.findRecord('table', data.to_table_id).then (table)=>@set('globals.active_list.table', table)
orders_in_process_count: (data)->
@set 'globals.list.supplier.orders_in_process_count', data.count
@set 'globals.active_list.supplier.orders_in_process_count', data.count
orders_placed_count: (data)->
@set 'globals.list.supplier.orders_placed_count', data.count
@set 'globals.active_list.supplier.orders_placed_count', data.count
new_order: (data)->
# return if @store.all('order').findProperty('id', data.order.id)
@store.pushPayload data
@store.findById('list', data.list.id).then (list)=> @set 'globals.list', list
# @store.findById('order', data.order.id).then (order)->
@store.peekRecord('list', data.list.id).then (list)=> @set 'globals.active_list', list
# @store.peekRecord('order', data.order.id).then (order)->
# list = order.get('list')
# list.get('orders').addObject(order)
@@ -92,15 +91,16 @@ App.ApplicationController = Ember.Controller.extend
list.set 'needs_payment', false
setCurrentList: (callback)->
success = (list)=>
#@store.find('list', 'current').deleteRecord() # gets not replaced, buty stays as dummy
#@store.findRecord('list', 'current').deleteRecord() # gets not replaced, buty stays as dummy
# A list record with id current and with the content of the returned list is created
# at the moment remove the dummy list, this should be resolved by Ember eventually
if error_list = @store.peekRecord('list', 'current')
# TODO: keek checking if peekAll can be replaced by peekRecord
if error_list = @store.peekAll('list', 'current').findBy('id', 'current') # peekRecord('list', 'current') not working in Ember 2.0.0
error_list.eraseRecord()
#TODO: depricate list on application controller
#@set 'list', list
@set 'globals.list', list
@set 'globals.active_list', list
if list.get('join_requests.length')
@transitionToRoute 'join_requests'
else if @currentRouteName is 'index'
@@ -112,7 +112,7 @@ App.ApplicationController = Ember.Controller.extend
#console.log "Error: #{emberError.message}" if emberError.message
if error_list = @store.peekRecord('list', 'current')
error_list.eraseRecord()
@set 'globals.list', null
@set 'globals.active_list', null
switch @currentRouteName
when 'table' then # nothing
else @redirect_to 'user_root'
@@ -1,5 +1,5 @@
App.JoinRequestsController = Ember.Controller.extend
join_requests: (-> @get('globals.list.join_requests') ).property('globals.list.join_requests')
join_requests: Ember.computed.alias 'globals.active_list.join_requests'
actions:
rejectRequest: (join_request)->
Ember.$.post("#{$data_host}/user/reject_join_request", user_id: join_request.get('user.id')).then (response)->
@@ -1,21 +1,19 @@
App.TableController = Ember.Controller.extend
tableCanTakeOrders: (->
return false unless @get('supplier.can_take_orders')
list = @get('globals.list')
if list
if list = @get('globals.active_list')
return false unless list.get('supplier.id') == @get('supplier.id')
return false unless list.get('table.id') == @get('model.id')
true
else
# no list and open supplier
if @get('model.occupied') then false else true
).property('globals.list.id', 'supplier.can_take_orders', 'model.occupied', 'model.id', 'globals.list.table.id')
supplier: Ember.computed 'model.supplier', -> @get('model.supplier')
showJoinButton: (->
).property('globals.active_list.id', 'supplier.can_take_orders', 'model.occupied', 'model.id', 'globals.active_list.table.id')
supplier: Ember.computed.alias 'model.supplier'
showJoinButton: Ember.computed 'globals.active_list.id', 'supplier.can_take_orders', 'model.occupied', 'model.id', 'globals.active_list.table.id', ->
return false unless @get('supplier.can_take_orders')
return false if @get('globals.list') # if you already have an active list, do not join another
return false if @get('globals.active_list') # if you already have an active list, do not join another
if @get('model.occupied') then true else false # no point in joining tables that are not occupied
).property('globals.list.id', 'supplier.can_take_orders', 'model.occupied', 'model.id', 'globals.list.table.id')
actions:
joinOccupiedTable: ->
Ember.$.post("#{$data_host}/user/join_occupied_table.json", table_id: @get('model.id'))
@@ -1,4 +1,4 @@
attr = DS.attr
App.JoinRequest= DS.Model.extend
list: DS.belongsTo('list')
user: DS.belongsTo('user')
list: DS.belongsTo('list', async: false)
user: DS.belongsTo('user', async: false)
@@ -1,31 +1,31 @@
attr = DS.attr
App.List = DS.Model.extend
orders: DS.hasMany('order')
needs_help: attr('boolean')
needs_payment: attr('boolean')
user_requests_closing: attr('boolean')
needs_help: attr('boolean', defaultValue: false)
needs_payment: attr('boolean', defaultValue: false)
user_requests_closing: attr('boolean', defaultValue: false)
state: attr('string')
price: attr('number')
closed_at: DS.attr('date')
closed_at: attr('date')
extended_version: attr('boolean')
supplier_orders_in_process_count: attr('number')
supplier_orders_placed_count: attr('number')
cached_supplier_name: attr('string')
supplier: DS.belongsTo('supplier')
table: DS.belongsTo('table')
join_requests: DS.hasMany('join_request')
users: DS.hasMany('user')
orders: DS.hasMany('order', async: true)
supplier: DS.belongsTo('supplier', async: false)
table: DS.belongsTo('table', async: true)
join_requests: DS.hasMany('join_request', async: false)
users: DS.hasMany('user', async: false)
is_extended_version: ->
@get('extended_version')
relevant_orders: (-> @get('orders').filter((o)->o.get('state') isnt 'cancelled')).property('orders.@each.state')
relevant_orders: Ember.computed 'orders.@each.state', -> @get('orders').rejectBy('state', 'cancelled')
sorted_orders: (-> @get('relevant_orders').sortBy('created_at').reverseObjects()).property('relevant_orders.@each.isLoaded')
total: (->
@get('relevant_orders').getEach('total').reduce(((sum, total) -> sum + total), 0)
).property('relevant_orders.@each.total')
active: (-> @get('state') is 'active' ).property('state')
active: Ember.computed.equal 'state', 'active'
showTotal: (->
if @get('orders.length') && @get('orders.length') > 1 then true else false
).property('orders.length')
#showTotal: (->
# if @get('orders.length') && @get('orders.length') > 1 then true else false
#).property('orders.length')
showTotal: Ember.computed.gt 'relevant_orders.length', 1
@@ -1,9 +1,9 @@
attr = DS.attr
App.Order = DS.Model.extend
state: attr 'string'
list: DS.belongsTo('list')
list: DS.belongsTo('list', async: true)
table: DS.belongsTo('table')
product_orders: DS.hasMany('product_order', embedded: 'always')
product_orders: DS.hasMany('product_order', async: false)
total: (->
@get('product_orders').getEach('total').reduce(((sum, total) -> sum + total), 0)
).property('product_orders.@each.quantity')
@@ -2,16 +2,16 @@ attr = DS.attr
App.ProductOrder = DS.Model.extend
quantity: attr 'number', defaultValue: 1
price: attr 'number'
product_name: attr('string')
product: DS.belongsTo('product')
product_name: attr 'string'
product_variant: attr('string')
order: DS.belongsTo('order')
placed: attr('boolean', defaultValue: false) # virtual attribute for new orders to be placed, should be more elegant
product: DS.belongsTo('product', async: true)
order: DS.belongsTo('order', async: false)
increment: ->
@set('quantity', @get('quantity') + 1)
total: (-> @get('quantity') * @get('price')).property('quantity', 'price')
display: Ember.computed 'quantity', 'product_variant', 'product.name', ->
disp = "#{@get('quantity')} x #{@get('product.name')}"
display: Ember.computed 'quantity', 'product_variant', 'product_name', ->
disp = "#{@get('quantity')} x #{@get('product_name')}"
if variant = @get('product_variant')
disp = "#{disp} (#{variant})"
disp.htmlSafe()
@@ -7,8 +7,8 @@ App.Supplier= DS.Model.extend
orders_placed_count: attr('number')
orders: DS.hasMany('order')
product_categories: DS.hasMany('product_category')
lists: DS.hasMany('list')
product_categories: DS.hasMany('product_category', async: true)
lists: DS.hasMany('list', async: true)
is_extended_version: ->
@get('extended_version')
@@ -4,4 +4,4 @@ App.Table= DS.Model.extend
needs_help: attr('boolean')
occupied: attr('boolean')
supplier: DS.belongsTo('supplier')
supplier: DS.belongsTo('supplier', async: true)
@@ -1,6 +1,6 @@
DS.Model.reopen
created_at: DS.attr('date')
updated_at: DS.attr('date')
#created_at: DS.attr('date')
#updated_at: DS.attr('date')
eraseRecord: ->
#@clearRelationships()
@transitionTo('deleted.saved')
@@ -1,6 +1,6 @@
App.ActiveListRoute = Ember.Route.extend App.ResetScroll
#model: ->
#@get('globals.list')
#@get('globals.active_list')
#afterModel: ->
#controller = @controllerFor('application')
#table_id = controller.get('list.table.id')
@@ -13,7 +13,7 @@ App.ApplicationRoute = Ember.Route.extend
unauthorized: ->
Qstorage.removeItem('auth_token')
Qstorage.removeItem('user_id')
@set 'globals.list', null
@set 'globals.active_list', null
#@send 'obtain_token'
@controllerFor('application').redirect_to 'sign_in', message: 'unauthorized'
@@ -76,13 +76,13 @@ App.ApplicationRoute = Ember.Route.extend
listNeedsPayment: ->
@get('controller').secured ->
@set 'globals.list.needs_payment', true
@set 'globals.active_list.needs_payment', true
Ember.$.post "#{$data_host}/user/list_needs_payment.json"
#Ember.$.post("#{$data_host}/user/list_needs_payment.json").then (res) =>
#@set('list.needs_payment', true) # also done by faye
listNeedsHelp: ->
@get('controller').secured ->
@set 'globals.list.needs_help', true
@set 'globals.active_list.needs_help', true
Ember.$.post "#{$data_host}/user/needs_help.json"
#Ember.$.post("#{$data_host}/user/needs_help.json").then (res) =>
#@set('list.needs_help', true) # also done by faye
@@ -1,5 +1,5 @@
App.ListRoute = Ember.Route.extend App.ResetScroll,
model: (options)->
@store.find 'list', options.list_id
@store.findRecord 'list', options.list_id
afterModel: (model)->
model.reload() unless model.is_extended_version()
@@ -1,5 +1,5 @@
App.ListsRoute = Ember.Route.extend App.ResetScroll,
model: ->
@store.find 'list'
@store.findAll 'list'
setupController: (controller, model)->
controller.set('alreadyLoaded', true)
@@ -1,7 +1,10 @@
App.ApplicationSerializer = DS.ActiveModelSerializer.extend()
App.ApplicationAdapter = DS.ActiveModelAdapter.extend
#App.ApplicationSerializer = DS.ActiveModelSerializer.extend()
App.ApplicationSerializer = DS.JSONAPISerializer.extend
keyForAttribute: (attr, method)-> attr
#App.ApplicationAdapter = DS.ActiveModelAdapter.extend
App.ApplicationAdapter = DS.JSONAPIAdapter.extend
host: $data_host
namespace: 'user'
headers:
"Accept": "application/json, text/javascript; q=0.01"
#headers:
# "Accept": "application/json, text/javascript; q=0.01"
@@ -13,7 +13,7 @@ if list.closed_at
.display-row
.display-label=t 'models.supplier'
.display-field= list.supplier.name
if list.orders.isLoaded
if list.isLoaded
if list.sorted_orders
.list-orders-container
each list.sorted_orders as |order|
@@ -30,7 +30,7 @@ if list.orders.isLoaded
span=t 'active_list.no_orders_explanation'
br
if list.table
link-to 'table' list.table class="button"
= link-to 'table' list.table class="button"
span=t 'list_products.title'
else
span.loading.large
@@ -1,13 +1,13 @@
.row
h2=t 'active_list.title'
if list.orders.isLoaded
if list.isLoaded
if list
partial "list_content"
else
p
span=t 'active_list.not_active.message'
br
link-to 'index' class="button"
= link-to 'index' class="button"
span= t 'active_list.not_active.home_button_text'
else
span.loading.large
@@ -9,9 +9,9 @@
a{action "scanQr" bubbles=false}
span.scan-qr-icon
span Scan QR
if globals.list.id
if globals.active_list.id
li
=link-to 'table' globals.list.table.id class="side-menu-list-products"
=link-to 'table' globals.active_list.table.id class="side-menu-list-products"
span.fa.fa-cutlery
span.fa.fa-glass
= t 'list_products.title'
@@ -19,7 +19,7 @@
=link-to 'active_list' class="side-menu-active-list"
span.active-list-icon
span= t 'active_list.title'
if globals.list.join_requests.length
if globals.active_list.join_requests.length
li
=link-to 'join_requests'
span= t 'models.plural.join_request'
@@ -2,11 +2,11 @@
.top-menu-bar
.menu-content
section.main-buttons
if globals.list.id
if globals.active_list.id
link-to 'index' class="top-menu-logo with-list"
= image-tag 'user/logo-small.png'
= menu-item route="active_list"
= menu-item route="table" route_param=globals.list.table.id
= menu-item route="table" route_param=globals.active_list.table.id
= menu-item-list-needs-help
= menu-item-list-needs-payment
else
@@ -14,18 +14,18 @@
= image-tag 'user/logo-small.png'
= menu-item-scan-qr
= menu-item-product-orders
if globals.list
if globals.active_list
.extra-info{action "showSupplierStatusInfo"}
.supplier-info-row
/ .supplier-name= list.supplier.name
.table-number
|#&nbsp;
= globals.list.table.number
= globals.active_list.table.number
.supplier-info-row
.counter.supplier-orders-placed-count
= globals.list.supplier.orders_placed_count
= globals.active_list.supplier.orders_placed_count
span.orders-placed-count-icon
.supplier-info-row
.counter.supplier-orders-in-process-count
= globals.list.supplier.orders_in_process_count
= globals.active_list.supplier.orders_in_process_count
span.orders-in-process-count-icon
@@ -1,3 +1,3 @@
span.created_at=time list.created_at
span.price.currency= currency list.price
span.name= list.cached_supplier_name
span.name= list.supplier.name
@@ -24,6 +24,8 @@
.currency
float: right
margin-right: 0.5em
min-width: 60px
text-align: right
.list-order-container
background-position: left center
background-repeat: no-repeat
@@ -0,0 +1,7 @@
module Users
module Lists
class OrdersController < Users::ApplicationController
respond_to :json
end
end
end
+8 -11
View File
@@ -7,24 +7,21 @@ module Users
#lists.include_relation(:supplier)
lists.reject!{|l| l.id == params[:exclude_list]} if params[:exclude_list].present?
lists.reject!{|l| l.id == current_user.active_list_id } if current_user && current_user.active_list_id.present? # see spec Loading lists and switching to the order products view works, lists loading may unlink active list orders
lists.include_relation(:users, :orders, :supplier)
render json: lists, each_serializer: UserListSerializer, meta: {total_pages: lists.total_pages, page: lists.current_page} #, root: :lists
lists.include_relation(:users, :supplier)
render json: lists, each_serializer: Users::ListSerializer, meta: {total_pages: lists.total_pages, page: lists.current_page} #, root: :lists
end
#EMBER
def current
list = current_user.active_list
render json: {}, status: :not_found and return unless list.present?
[list].include_relation(supplier: {product_categories: :products}, orders: :product_orders) # table also when it is a real array :)
render json: json_response(not_present: true) and return unless list.present?
render json: list, serializer: UserExtendedListSerializer
@list = current_user.active_list
show
end
def show
list = List.find(params[:id])
render json: {}, status: :not_found and return unless list.present? && Array.wrap(list.user_ids).include?(current_user.id)
[list].include_relation(supplier: {product_categories: :products}, orders: :product_orders) # table also when it is a real array :)
render json: list, serializer: UserExtendedListSerializer
@list ||= List.find(params[:id])
render json: {}, status: :not_found and return unless @list.present? && Array.wrap(@list.user_ids).include?(current_user.id)
[@list].include_relation(:users)
render json: @list, serializer: Users::ListSerializer, include: %w[supplier users]
end
end
end
+10 -1
View File
@@ -2,6 +2,15 @@ module Users
class OrdersController < Users::ApplicationController
respond_to :json
# /nested resource
def index
render json: {}, status: :not_found and return unless params[:list_id].present?
@list = List.find(params[:list_id])
render json: {}, status: :not_found and return unless @list.present? && Array.wrap(@list.user_ids).include?(current_user.id)
orders = @list.orders.include_relation(:product_orders)
render json: orders, each_serializer: Users::OrderSerializer, include: %w[product_orders]
end
# Used by the user Ember app
# POST /user/orders
def create
@@ -25,7 +34,7 @@ module Users
list = List.from_table( table, current_user )
end
order = list.place_order product_orders: params[:product_orders], user: current_user
render json: order, serializer: OrderSerializer
render json: order, serializer: Users::OrderSerializer
#render nothing: true
end
end
+1 -1
View File
@@ -2,7 +2,7 @@ module Users
class TablesController < Users::ApplicationController
def show
@table = Table.find(params[:id])
render json: @table, serializer: UserExtendedTableSerializer
render json: @table, serializer: Users::TableSerializer
end
end
end
+2 -2
View File
@@ -307,10 +307,10 @@ class List
# broadcast_users 'new_order', order: order.with_products_as_json, total_amount: price
broadcast_users 'new_order', UserExtendedListSerializer.new(order.list).as_json
broadcast_users 'new_order', Users::OrderSerializer.new(order).as_json
# broadcast_users 'orders_placed_count', count: orders_placed_count
broadcast_supplier supplier.id, 'list_update', SupplierListSerializer.new(self).as_json.merge(new_order_id: order.id)
broadcast_supplier supplier.id, 'list_update', Supplier::ListSerializer.new(self).as_json.merge(new_order_id: order.id)
# broadcast_supplier supplier.id, 'new_order', OrderSerializer.new(order)
broadcast_supplier supplier.id, 'orders_placed_count', count: orders_placed_count
order
+1 -1
View File
@@ -1,4 +1,4 @@
class JoinRequestSerializer < Qwaiter::Serializer
attributes :list_id
has_one :user, serializer: UserUserSerializer
has_one :user, serializer: Users::UserSerializer
end
+1 -1
View File
@@ -1,4 +1,4 @@
# Used for user ember1
class ProductOrderSerializer < Qwaiter::Serializer
attributes :order_id, :product_id, :quantity, :price, :product_name, :product_variant
attributes :quantity, :price, :product_name, :product_variant
end
@@ -21,9 +21,9 @@ class UserExtendedListSerializer < Qwaiter::Serializer
end
has_many :orders
#has_many :product_categories
has_one :table, serializer: UserExtendedTableSerializer # this one add a lot of stuff
has_one :table, serializer: Users::TableSerializer # this one add a lot of stuff
has_many :join_requests, serializer: JoinRequestSerializer
has_many :users, serializer: UserUserSerializer
has_many :users, serializer: Users::UserSerializer
#has_one :supplier # added by other resource
def extended_version
-20
View File
@@ -1,20 +0,0 @@
class UserListSerializer < Qwaiter::Serializer
# user ids for facebook pictures
attributes :state, :needs_help, :needs_payment, :user_requests_closing,
:is_paid, :price, :table_id, :table_number, :section_id, :user_ids,
:cached_supplier_name, :closed_at, :supplier_id, :extended_version
#def has_active_orders
#object.has_active_orders?
#end
def cached_supplier_name
object.supplier.name
end
def extended_version
false
end
# has_many :users, serializer: UserUserSerializer
# has_many :orders
# has_one :supplier, serializer: UserSupplierSerializer
end
-4
View File
@@ -1,4 +0,0 @@
class UserTableSerializer < Qwaiter::Serializer
self.root = :table
attributes :number, :width, :height, :position_x, :position_y, :section_id, :occupied, :needs_help
end
+11
View File
@@ -0,0 +1,11 @@
class Users::ListSerializer < Qwaiter::Serializer
# user ids for facebook pictures
self.root = :list
attributes :state, :needs_help, :needs_payment, :user_requests_closing,
:is_paid, :price, :closed_at
has_many :users, serializer: Users::UserSerializer
has_many :orders, url: ->(list){ "/user/lists/#{list.id}/orders" }, serializer: OrderSerializer
has_one :supplier, serializer: Users::SupplierSerializer
#belongs_to :table
end
@@ -0,0 +1,8 @@
class Users::OrderSerializer < Qwaiter::Serializer
attributes :state #, :list_id, :section_id, :table_id #, :price
has_many :product_orders, serializer: Users::ProductOrderSerializer
belongs_to :list
#belongs_to :section
#belongs_to :table
end
@@ -0,0 +1,6 @@
# Used for user ember1
class Users::ProductOrderSerializer < Qwaiter::Serializer
attributes :quantity, :price, :product_name, :product_variant
# belongs_to :product #DO NOT USE THIS, THIS IS NOT NEEDED
belongs_to :order
end
@@ -1,4 +1,4 @@
class UserSupplierSerializer < Qwaiter::Serializer
class Users::SupplierSerializer < Qwaiter::Serializer
self.root = :supplier
attributes :extended_version, :open, :name
+12
View File
@@ -0,0 +1,12 @@
class Users::TableSerializer < Qwaiter::Serializer
self.root = :table
attributes :number, :width, :height, :position_x, :position_y, :section_id, :occupied, :supplier_id #, :alist_id
#def list_id
#object.active_list_id || object.active_list.try(:id)
#end
#def list
#object.active_list
#end
end
@@ -1,4 +1,4 @@
class UserUserSerializer < Qwaiter::Serializer
class Users::UserSerializer < Qwaiter::Serializer
self.root = :user
attributes :email, :provider, :uid, :name, :avatar
+77 -3
View File
@@ -1,4 +1,78 @@
ActiveModel::Serializer.setup do |config|
config.embed = :ids
config.embed_in_root = true
#ActiveModel::Serializer.setup do |config|
# config.embed = :ids
# config.embed_in_root = true
# config.adapter = :json_api
#end
module ActiveModel::SerializerSupport
def read_attribute_for_serialization(attr)
public_send attr
end
end
class Qwaiter::JsonAdapter < ActiveModel::Serializer::Adapter::JsonApi
def add_resource_relationships(attrs, serializer, options = {})
options[:add_included] = options.fetch(:add_included, true)
serializer.class._associations.dup.each do |name, association_options| #do |name, association, opts|
next unless object = serializer.object
if association_options[:type] == :has_many
# todo check for object["#{name}_ids"]
association_value = association_options[:association_options][:url] ? [] : serializer.send(name)
association_serializer_class = ActiveModel::Serializer.serializer_for(association_value, association_options)
else
# Only load if the record has to be included anyway or no id value can be found
if include_assoc?(name)
association_value = serializer.send(name)
else
association_id = object["#{name}_id"]
association_class= name.to_s.classify.safe_constantize
if association_id && association_class
association_value = association_class.new(id: association_id)
else
association_value = serializer.send(name)
end
end
association_serializer_class = ActiveModel::Serializer.serializer_for(association_value, association_options)
end
if association_serializer_class
association_serializer = association_serializer_class.new(
association_value,
options.except(:serializer).merge(serializer.serializer_from_options(association_options))
)
elsif !association_value.nil? && !association_value.instance_of?(Object)
association_options[:association_options][:virtual_value] = association_value
end
opts = association_options[:association_options]
attrs[:relationships] ||= {}
if association_serializer.respond_to?(:each)
if opts[:url]
add_related(attrs, name, serializer.object, opts[:url])
else
add_relationships(attrs, name, association_serializer)
end
else
if opts[:virtual_value]
add_relationship(attrs, name, nil, opts[:virtual_value])
else
add_relationship(attrs, name, association_serializer)
end
end
if options[:add_included]
Array(association_serializer).each do |association|
add_included(name, association)
end
end
end
end
def add_related(resource, name, record, related)
related_url = related.is_a?(Proc) ? related.call(record) : related
resource[:relationships] ||= {}
resource[:relationships][name] ||= { links: {} }
resource[:relationships][name][:links][:related] = related_url
end
end
#ActiveModel::Serializer.config.adapter = :json_api
ActiveModel::Serializer.config.adapter = Qwaiter::JsonAdapter
+1
View File
@@ -82,6 +82,7 @@ Qwaiter::Application.routes.draw do
collection do
get :current
end
resources :orders, only: [:index]
end
resources :orders, only: [:create]
+22
View File
@@ -1,7 +1,14 @@
module Qwaiter
class Serializer < ActiveModel::Serializer
def self.root=(val)
ActiveSupport::Deprecation.new('1.0', 'Mozo')
end
def self.root(val)
ActiveSupport::Deprecation.new('1.0', 'Mozo')
end
# attribute :_id, key: :id
attributes :id, :created_at, :updated_at
# Bug in rails 4.1 serializing symbols in jsonify
#def to_json(*args)
#as_json.to_json(*args)
@@ -10,6 +17,21 @@ module Qwaiter
#def id
#object._id
#end
def created_at
timestamp_attribute :created_at
end
def updated_at
timestamp_attribute :updated_at
end
private
def timestamp_attribute(attr)
timestamp = object.send(attr)
return nil unless timestamp
timestamp.iso8601
end
end
end
+1
View File
@@ -1,5 +1,6 @@
FactoryGirl.define do
factory :product_order do
quantity 1
association :order
association :product
end
@@ -0,0 +1,30 @@
require 'spec_helper'
describe Users::OrderSerializer do
let(:adapter){ ActiveModel::Serializer.config.adapter }
it "does not perform extra queries" do
l = create :list
o1 = create :order, list: l
create :product_order, order: o1
create :product_order, order: o1
o2 = create :order, list: l
create :product_order, order: o2
create :product_order, order: o2
list = List.find(l.id)
orders = list.orders.include_relation(:product_orders)
#expect{ object_as_json orders }.not_to exceed_query_limit 0
expect{ object_as_json orders }.not_to perform_any_queries
result = object_as_json(orders)
binding.pry
#result[:included].size.should eq 4
end
def object_as_json(obj)
serializer = if obj.is_a?(Array)
ActiveModel::Serializer::ArraySerializer.new(obj, serializer: described_class, add_included: true)
else
serializer = described_class.new(obj)
end
adapter.new(serializer, include: %w[product_orders]).as_json
end
end
+88
View File
@@ -0,0 +1,88 @@
$performed_queries = []
CouchRest.class_eval do
class << self
alias_method :old_get, :get
def get(uri, options={})
$performed_queries << {url: uri, options: options} if is_query_uri?(uri)
old_get(uri, options)
end
def is_query_uri?(uri)
return false if uri =~ /\/_design\/\w+$/ # request design doc
return false if uri =~ /\/_uuids/
true
end
end
end
# taken from: http://stackoverflow.com/questions/5490411/counting-the-number-of-queries-performed
RSpec::Matchers.define :exceed_query_limit do |expected|
match do |block|
query_count(&block) > expected
end
failure_message_when_negated do |actual|
extra_queries = $performed_queries[expected..-1].map{|q| q[:url]}.map do |q|
if q =~ /5984\/\w+\/[0-9a-f]{32}$/
info = q
begin
record = CouchRest.get(q)
if record.is_a?(SimplyStored::Couch)
info += " #{record.class.name}"
end
rescue
end
info
else
q
end
end
"Expected to run maximum #{expected} queries, got #{@executed_queries}\nExtra queries:\n - #{extra_queries.join("\n - ")}"
end
def query_count(&block)
$performed_queries = []
block.call
@executed_queries = $performed_queries.size
end
def supports_block_expectations?
true
end
end
RSpec::Matchers.define :perform_any_queries do |expected|
match do |block|
query_count(&block) > 0
end
failure_message_when_negated do |actual|
extra_queries = $performed_queries.map{|q| q[:url]}.map do |q|
if q =~ /5984\/\w+\/[0-9a-f]{32}$/
info = q
begin
record = CouchRest.get(q)
if record.is_a?(SimplyStored::Couch)
info += " #{record.class.name}"
end
rescue
end
info
else
q
end
end
"Expected to run no queries, got #{@executed_queries}\nExtra queries:\n - #{extra_queries.join("\n - ")}"
end
def query_count(&block)
$performed_queries = []
block.call
@executed_queries = $performed_queries.size
end
def supports_block_expectations?
true
end
end