0

I am trying to chart a line graph that displays by orders by the date the were created and I am running into an issue.

Here is the index.html.erb snippet for my home controller causing the error

<%= line_chart @orders.map { |order|
    {name: order.id, data: order.created_at.group_by_day(:created_at, default_value: "missing", time_zone: "Kolkata").count}
} %>

I am receiving the following error:

 undefined method `group_by_day' for "2018-04-12T22:01:52-04:00":String

I have the groupdate and chartkick gems included in my Gemfile, which seems to be the common fix. Any help would be appreciated. Please let me know if you need additional information.

Full Trace:

app/views/home/index.html.erb:14:in `block in _app_views_home_index_html_erb__895458771_51649740'
activeresource (5.0.0) lib/active_resource/collection.rb:8:in `map'
activeresource (5.0.0) lib/active_resource/collection.rb:8:in `map'
app/views/home/index.html.erb:13:in `_app_views_home_index_html_erb__895458771_51649740'
actionview (5.1.6) lib/action_view/template.rb:157:in `block in render'
activesupport (5.1.6) lib/active_support/notifications.rb:168:in `instrument'
actionview (5.1.6) lib/action_view/template.rb:352:in `instrument_render_template'
actionview (5.1.6) lib/action_view/template.rb:155:in `render'
actionview (5.1.6) lib/action_view/renderer/template_renderer.rb:52:in `block (2 levels) in render_template'
actionview (5.1.6) lib/action_view/renderer/abstract_renderer.rb:42:in `block in instrument'
activesupport (5.1.6) lib/active_support/notifications.rb:166:in `block in instrument'
activesupport (5.1.6) lib/active_support/notifications/instrumenter.rb:21:in `instrument'
activesupport (5.1.6) lib/active_support/notifications.rb:166:in `instrument'
actionview (5.1.6) lib/action_view/renderer/abstract_renderer.rb:41:in `instrument'
actionview (5.1.6) lib/action_view/renderer/template_renderer.rb:51:in `block in render_template'
actionview (5.1.6) lib/action_view/renderer/template_renderer.rb:59:in `render_with_layout'
actionview (5.1.6) lib/action_view/renderer/template_renderer.rb:50:in `render_template'
actionview (5.1.6) lib/action_view/renderer/template_renderer.rb:14:in `render'
actionview (5.1.6) lib/action_view/renderer/renderer.rb:42:in `render_template'
actionview (5.1.6) lib/action_view/renderer/renderer.rb:23:in `render'
actionview (5.1.6) lib/action_view/rendering.rb:103:in `_render_template'
actionpack (5.1.6) lib/action_controller/metal/streaming.rb:217:in `_render_template'
actionview (5.1.6) lib/action_view/rendering.rb:83:in `render_to_body'
actionpack (5.1.6) lib/action_controller/metal/rendering.rb:52:in `render_to_body'
actionpack (5.1.6) lib/action_controller/metal/renderers.rb:141:in `render_to_body'
actionpack (5.1.6) lib/abstract_controller/rendering.rb:24:in `render'
actionpack (5.1.6) lib/action_controller/metal/rendering.rb:36:in `render'
actionpack (5.1.6) lib/action_controller/metal/instrumentation.rb:44:in `block (2 levels) in render'
activesupport (5.1.6) lib/active_support/core_ext/benchmark.rb:12:in `block in ms'
C:/Ruby24-x64/lib/ruby/2.4.0/benchmark.rb:308:in `realtime'
activesupport (5.1.6) lib/active_support/core_ext/benchmark.rb:12:in `ms'
actionpack (5.1.6) lib/action_controller/metal/instrumentation.rb:44:in `block in render'
actionpack (5.1.6) lib/action_controller/metal/instrumentation.rb:87:in `cleanup_view_runtime'
activerecord (5.1.6) lib/active_record/railties/controller_runtime.rb:29:in `cleanup_view_runtime'
actionpack (5.1.6) lib/action_controller/metal/instrumentation.rb:43:in `render'
actionpack (5.1.6) lib/action_controller/metal/implicit_render.rb:33:in `default_render'
actionpack (5.1.6) lib/action_controller/metal/basic_implicit_render.rb:4:in `block in send_action'
actionpack (5.1.6) lib/action_controller/metal/basic_implicit_render.rb:4:in `tap'
actionpack (5.1.6) lib/action_controller/metal/basic_implicit_render.rb:4:in `send_action'
actionpack (5.1.6) lib/abstract_controller/base.rb:186:in `process_action'
actionpack (5.1.6) lib/action_controller/metal/rendering.rb:30:in `process_action'
actionpack (5.1.6) lib/abstract_controller/callbacks.rb:20:in `block in process_action'
activesupport (5.1.6) lib/active_support/callbacks.rb:108:in `block in run_callbacks'
shopify_app (8.2.6) lib/shopify_app/controller_concerns/login_protection.rb:15:in `shopify_session'
activesupport (5.1.6) lib/active_support/callbacks.rb:117:in `block in run_callbacks'
activesupport (5.1.6) lib/active_support/callbacks.rb:135:in `run_callbacks'
actionpack (5.1.6) lib/abstract_controller/callbacks.rb:19:in `process_action'
actionpack (5.1.6) lib/action_controller/metal/rescue.rb:20:in `process_action'
actionpack (5.1.6) lib/action_controller/metal/instrumentation.rb:32:in `block in process_action'
activesupport (5.1.6) lib/active_support/notifications.rb:166:in `block in instrument'
activesupport (5.1.6) lib/active_support/notifications/instrumenter.rb:21:in `instrument'
activesupport (5.1.6) lib/active_support/notifications.rb:166:in `instrument'
actionpack (5.1.6) lib/action_controller/metal/instrumentation.rb:30:in `process_action'
actionpack (5.1.6) lib/action_controller/metal/params_wrapper.rb:252:in `process_action'
activerecord (5.1.6) lib/active_record/railties/controller_runtime.rb:22:in `process_action'
actionpack (5.1.6) lib/abstract_controller/base.rb:124:in `process'
actionview (5.1.6) lib/action_view/rendering.rb:30:in `process'
actionpack (5.1.6) lib/action_controller/metal.rb:189:in `dispatch'
actionpack (5.1.6) lib/action_controller/metal.rb:253:in `dispatch'
actionpack (5.1.6) lib/action_dispatch/routing/route_set.rb:49:in `dispatch'
actionpack (5.1.6) lib/action_dispatch/routing/route_set.rb:31:in `serve'
actionpack (5.1.6) lib/action_dispatch/journey/router.rb:50:in `block in serve'
actionpack (5.1.6) lib/action_dispatch/journey/router.rb:33:in `each'
actionpack (5.1.6) lib/action_dispatch/journey/router.rb:33:in `serve'
actionpack (5.1.6) lib/action_dispatch/routing/route_set.rb:844:in `call'
omniauth (1.8.1) lib/omniauth/strategy.rb:190:in `call!'
omniauth (1.8.1) lib/omniauth/strategy.rb:168:in `call'
omniauth (1.8.1) lib/omniauth/builder.rb:63:in `call'
rack (2.0.4) lib/rack/etag.rb:25:in `call'
rack (2.0.4) lib/rack/conditional_get.rb:25:in `call'
rack (2.0.4) lib/rack/head.rb:12:in `call'
rack (2.0.4) lib/rack/session/abstract/id.rb:232:in `context'
rack (2.0.4) lib/rack/session/abstract/id.rb:226:in `call'
actionpack (5.1.6) lib/action_dispatch/middleware/cookies.rb:613:in `call'
activerecord (5.1.6) lib/active_record/migration.rb:556:in `call'
actionpack (5.1.6) lib/action_dispatch/middleware/callbacks.rb:26:in `block in call'
activesupport (5.1.6) lib/active_support/callbacks.rb:97:in `run_callbacks'
actionpack (5.1.6) lib/action_dispatch/middleware/callbacks.rb:24:in `call'
actionpack (5.1.6) lib/action_dispatch/middleware/executor.rb:12:in `call'
actionpack (5.1.6) lib/action_dispatch/middleware/debug_exceptions.rb:59:in `call'
web-console (3.6.0) lib/web_console/middleware.rb:137:in `call_app'
web-console (3.6.0) lib/web_console/middleware.rb:22:in `block in call'
web-console (3.6.0) lib/web_console/middleware.rb:20:in `catch'
web-console (3.6.0) lib/web_console/middleware.rb:20:in `call'
actionpack (5.1.6) lib/action_dispatch/middleware/show_exceptions.rb:31:in `call'
railties (5.1.6) lib/rails/rack/logger.rb:36:in `call_app'
railties (5.1.6) lib/rails/rack/logger.rb:24:in `block in call'
activesupport (5.1.6) lib/active_support/tagged_logging.rb:69:in `block in tagged'
activesupport (5.1.6) lib/active_support/tagged_logging.rb:26:in `tagged'
activesupport (5.1.6) lib/active_support/tagged_logging.rb:69:in `tagged'
railties (5.1.6) lib/rails/rack/logger.rb:24:in `call'
sprockets-rails (3.2.1) lib/sprockets/rails/quiet_assets.rb:13:in `call'
actionpack (5.1.6) lib/action_dispatch/middleware/remote_ip.rb:79:in `call'
actionpack (5.1.6) lib/action_dispatch/middleware/request_id.rb:25:in `call'
rack (2.0.4) lib/rack/method_override.rb:22:in `call'
rack (2.0.4) lib/rack/runtime.rb:22:in `call'
activesupport (5.1.6) lib/active_support/cache/strategy/local_cache_middleware.rb:27:in `call'
actionpack (5.1.6) lib/action_dispatch/middleware/executor.rb:12:in `call'
actionpack (5.1.6) lib/action_dispatch/middleware/static.rb:125:in `call'
rack (2.0.4) lib/rack/sendfile.rb:111:in `call'
railties (5.1.6) lib/rails/engine.rb:522:in `call'
puma (3.11.3) lib/puma/configuration.rb:225:in `call'
puma (3.11.3) lib/puma/server.rb:624:in `handle_request'
puma (3.11.3) lib/puma/server.rb:438:in `process_client'
puma (3.11.3) lib/puma/server.rb:302:in `block in run'
puma (3.11.3) lib/puma/thread_pool.rb:120:in `block in spawn_thread'

example order when printed :

#<ShopifyAPI::Order:0x00000000086f6780 @attributes={"id"=>380632137775, "email"=>"", "closed_at"=>nil, "created_at"=>"2018-04-12T22:01:52-04:00", "updated_at"=>"2018-04-12T22:01:52-04:00", "number"=>2, "note"=>"", "token"=>"hidden", "gateway"=>nil, "test"=>false, "total_price"=>"0.00", "subtotal_price"=>"0.00", "total_weight"=>0, "total_tax"=>"0.00", "taxes_included"=>false, "currency"=>"USD", "financial_status"=>"paid", "confirmed"=>true, "total_discounts"=>"0.00", "total_line_items_price"=>"0.00", "cart_token"=>nil, "buyer_accepts_marketing"=>false, "name"=>"#1002", "referring_site"=>nil, "landing_site"=>nil, "cancelled_at"=>nil, "cancel_reason"=>nil, "total_price_usd"=>"0.00", "checkout_token"=>nil, "reference"=>nil, "user_id"=>10752655407, "location_id"=>6268256303, "source_identifier"=>nil, "source_url"=>nil, "processed_at"=>"2018-04-12T22:01:52-04:00", "device_id"=>nil, "phone"=>nil, "customer_locale"=>nil, "app_id"=>1354745, "browser_ip"=>nil, "landing_site_ref"=>nil, "order_number"=>1002, "discount_codes"=>[], "note_attributes"=>[], "payment_gateway_names"=>[], "processing_method"=>"manual", "checkout_id"=>nil, "source_name"=>"shopify_draft_order", "fulfillment_status"=>nil, "tax_lines"=>[], "tags"=>"", "contact_email"=>nil, "order_status_url"=>"hidden", "line_items"=>[#<ShopifyAPI::LineItem:0x000000000866fc58 @attributes={"id"=>783789817903, "variant_id"=>7469149978671, "title"=>"Product #1", "quantity"=>1, "price"=>"0.00", "sku"=>"", "variant_title"=>nil, "vendor"=>"new-vision-nutritio-dev", "fulfillment_service"=>"manual", "product_id"=>639214125103, "requires_shipping"=>true, "taxable"=>true, "gift_card"=>false, "name"=>"Product #1", "variant_inventory_management"=>nil, "properties"=>[], "product_exists"=>true, "fulfillable_quantity"=>1, "grams"=>0, "total_discount"=>"0.00", "fulfillment_status"=>nil, "tax_lines"=>[#<ShopifyAPI::TaxLine:0x000000000865dcb0 @attributes={"title"=>"NJ State Tax", "price"=>"0.00", "rate"=>0.06625}, @prefix_options={}, @persisted=true>]}, @prefix_options={}, @persisted=true>], "shipping_lines"=>[], "fulfillments"=>[], "refunds"=>[]}, @prefix_options={}, @persisted=true> 
chris cozzens
  • 517
  • 4
  • 19
  • 1
    The issue is `created_at` is being treated as a string. Can you provide us with your `schema.rb` to ensure it is a timestamp? – Leo Correa Apr 13 '18 at 18:22
  • @LeoCorrea thanks for the response, I am using the Shopify Order API for my orders here. It looks like order.created_at should be returning a timestamp. Let me know what other info you need an ill get it over ASAP. – chris cozzens Apr 16 '18 at 15:15
  • 1
    So this information is not coming back from the database? If it's through an API and the format of the request is JSON then you'll have to convert the string into a DateTime object in ruby. It would be useful to see what is setting the `@orders` instance variable – Leo Correa Apr 16 '18 at 15:20
  • @LeoCorrea I have added an example of what one of the orders looks like when inspected. – chris cozzens Apr 16 '18 at 16:02
  • I have also tried {name: "order.id", data: order.created_at.to_datetime.group_by_day(:created_at, default_value: "missing", time_zone: "Kolkata").count} and get the following error undefined method `group_by_day' for Thu, 12 Apr 2018 22:01:52 -0400:DateTime – chris cozzens Apr 16 '18 at 16:05
  • Right, so I didn't realize `group_by_day` was a method from the gem https://github.com/ankane/groupdate and it only seems to work on ActiveRecord relations so that method won't work on data fetched from the Shopify API – Leo Correa Apr 16 '18 at 16:39

1 Answers1

2

If you look at the documentation for groupdate, the group_by_day method works on the collection of objects, not the specific attribute.

The following code works on the array of orders:

<%=  
  line_chart @orders.group_by_day(default_value: "missing", time_zone: "Kolkata") { |order|
  order.created_at
}.map { |date, orders| [date, orders.size] }
%>

From the docs on groupdate, group_by_day is a method that works on a collection of objects, either Enumerable or ActiveRecord collections. When called on an Enumerable object like an array, it uses the return value of the block to know which attribute of the object to group by, in this case your created_at attribute. The last method call to map returns data that chartkick can use to render the line graph, in this case chartkick expects an array of arrays which contain the date and the count of items per date (or some aggregated value).

Leo Correa
  • 19,131
  • 2
  • 53
  • 71
  • Im really sorry to do this to you, but can you please explain the syntax for me, I am having a hard time understanding why this works. – chris cozzens Apr 16 '18 at 20:43
  • Updated for a bit of clarity. It really helps to checkout the docs for each gem and understand how the gem can be used for your specific use case – Leo Correa Apr 17 '18 at 00:39