{"id":13515144,"url":"https://github.com/railsjazz/rails_charts","last_synced_at":"2025-11-11T18:34:14.165Z","repository":{"id":37559178,"uuid":"483380192","full_name":"railsjazz/rails_charts","owner":"railsjazz","description":"Rails Charts using eCharts from Apache","archived":false,"fork":false,"pushed_at":"2023-12-09T08:18:50.000Z","size":6742,"stargazers_count":156,"open_issues_count":4,"forks_count":18,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-03-29T04:12:13.705Z","etag":null,"topics":["charts","rails"],"latest_commit_sha":null,"homepage":"https://www.railsjazz.com/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/railsjazz.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGES","contributing":null,"funding":".github/FUNDING.yml","license":"MIT-LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null},"funding":{"patreon":"igorkasyanchuk"}},"created_at":"2022-04-19T19:20:56.000Z","updated_at":"2025-03-07T11:44:09.000Z","dependencies_parsed_at":"2023-12-09T09:36:15.418Z","dependency_job_id":null,"html_url":"https://github.com/railsjazz/rails_charts","commit_stats":{"total_commits":55,"total_committers":5,"mean_commits":11.0,"dds":0.1454545454545455,"last_synced_commit":"1d324f727cdcdd64c2c53974e2c22b3cd70de073"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/railsjazz%2Frails_charts","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/railsjazz%2Frails_charts/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/railsjazz%2Frails_charts/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/railsjazz%2Frails_charts/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/railsjazz","download_url":"https://codeload.github.com/railsjazz/rails_charts/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247289429,"owners_count":20914464,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["charts","rails"],"created_at":"2024-08-01T05:01:06.772Z","updated_at":"2025-11-11T18:34:14.147Z","avatar_url":"https://github.com/railsjazz.png","language":"JavaScript","funding_links":["https://patreon.com/igorkasyanchuk","https://buymeacoffee.com/igorkasyanchuk"],"categories":["JavaScript","Languages"],"sub_categories":["Ruby"],"readme":"# Rails Charts\n\n[![RailsJazz](https://github.com/igorkasyanchuk/rails_time_travel/blob/main/docs/my_other.svg?raw=true)](https://www.railsjazz.com)\n\n[![\"Buy Me A Coffee\"](https://github.com/igorkasyanchuk/get-smart/blob/main/docs/snapshot-bmc-button-small.png?raw=true)](https://buymeacoffee.com/igorkasyanchuk)\n\n![Charts](docs/all.jpg)\n\nOne more gem to build nice charts for your Ruby on Rails application.\n\nWith it you can build various types of charts [Apache eCharts](https://echarts.apache.org/) library (v. 6.0). This gem simplifies interface and adding few helpers to start adding charts in your app with just a few lines of code.\n\nWhat you can build with it:\n\n- [area chart](#area-chart)\n- [line chart](#line-chart)\n- [bar chart](#bar-chart)\n- [donut chart](#donut-chart)\n- [pie chart](#pie-chart)\n- [radar chart](#radar-chart)\n- [calendar chart](#calendar-chart)\n- [candlestick chart](#candlestick-chart)\n- [funnel chart](#funnel-chart)\n- [gauge chart](#gauge-chart)\n- [parallel chart](#parallel-chart)\n- [sankey chart](#sankey-chart)\n- [scatter chart](#scatter-chart)\n- [stacked bar chart](#stacked-bar-chart)\n- [custom chart](#custom-chart)\n\nIn most cases with one line of code you can have a nice chart. The idea of this gem was inspired by [Chartkick](https://github.com/ankane/chartkick) gem which is great and allows you to build charts very quickly. It works best in cooperation with [groupdate](https://github.com/ankane/groupdate) gem. Unfortunatelly it's missing many needed types of charts or other customization options.\n\nThis implementation have more options and similar \"interface\" for building charts.\n\n\n## Installation\n\nAdd gem to your application's Gemfile:\n\n```ruby\ngem \"rails_charts\"\n```\n\nThen execute:\n```bash\n$ ./bin/bundle install\n```\n\nYou can install ECharts with installation command\n\n```bash\n$ ./bin/rails rails_charts:install\n```\n\nor do it manualy\n\n### Sprockets\n\n1) add eCharts in main JS bundle, e.g. `app/assets/javascripts/application.js`\n\n```javascript\n//= require echarts.min.js\n//= require echarts/theme/dark.js\n```\n\n3) add your first chart e.g.\n```ruby\n\u003c%= line_chart User.group(:age).count %\u003e\n```\n\n4) customize charts if needed. See available options or [official documentation](https://echarts.apache.org/examples/en/index.html).\n\n\n### Webpack / esbuild\n\n1) Run:\n\n```bash\nyarn add echarts\n```\n\n#### For Rails 7\n2) In `app/javascript/application.js` add this:\n\n```javascript\nimport * as echarts from 'echarts';\nimport 'echarts/theme/dark';\n\nwindow.echarts = echarts;\n```\n\n#### For Rails 6\n2) In `app/javascript/packs/application.js` add this:\n\n```javascript\nimport * as echarts from 'echarts';\nimport 'echarts/theme/dark';\n\nwindow.echarts = echarts;\n```\n\n3) add your first chart e.g.\n```ruby\n\u003c%= line_chart User.group(:age).count %\u003e\n```\n\n4) customize charts if needed. See available options or [official documentation](https://echarts.apache.org/examples/en/index.html).\n\n### Importmaps\n\n1) change `config/importmap.rb`\n\n```ruby\npin \"echarts\", to: \"echarts.min.js\"\npin \"echarts/theme/dark\", to: \"echarts/theme/dark.js\"\n```\n\n2) add eCharts in main JS\n\n```javascript\nimport \"echarts\"\nimport \"echarts/theme/dark\"\n```\n\n3) add your first chart e.g.\n```ruby\n\u003c%= line_chart User.group(:age).count %\u003e\n```\n\n4) customize charts if needed. See available options or [official documentation](https://echarts.apache.org/examples/en/index.html).\n\n### Loading Themes\n\nThemes can be loaded as shown in examples above. However, in some cases where\nthemes are included in environment where `this` does not point to `window`, you\nmight get errors. In that case, you can use loadTheme helper to load themes by\nname. For example, instead of\n\n```javascript\nimport 'echarts/theme/dark'\n```\nyou can do\n\n```javascript\n// application.js\nimport \"echarts\"\nimport \"echarts.themeloader\"\n\n// Load the desired theme dynamically\nRailsCharts.loadTheme('dark');\n```\n\n## Options\n\n```ruby\n\u003c%= line_chart data, {\n  width: '250px',\n  height: '250px',\n  theme: 'dark',\n  class: 'chart-container-class',\n  style: 'padding: 10px'\n} %\u003e\n```\n\nAvailable options:\n\n```yaml\nwidth: specify width of the chart\nheight: specify height of the chart\ntheme: specify theme of the chart (available themes examples https://echarts.apache.org/en/download-theme.html)\nclass: specify container's CSS class\nid: specify container's ID\nstyle: add inline style\ndebug: for gem development useful if you want to pause somewhere in the code\nvertical: applicable for some types of charts\ncode: to see output code what is generated to see the chart, useful for debugging\noptions: {...}, nested hash, specify additional eCharts options\n```\n\nApache eCharts options - https://echarts.apache.org/en/option.html#title.\n\nIf you need to format tooltip (or other javascript function as an option) you can pass a JS function, but you need to wrap it like:\n\n```ruby\n  options: {\n    tooltip: {\n      valueFormatter: RailsCharts.js(\"(value) =\u003e '$' + Math.round(value)\")\n    }\n  }\n```\n\n## Charts\n\nAll examples available in https://github.com/railsjazz/rails_charts/tree/main/test/dummy/app/views/home. You can see more examples if you clone this repo and start a dummy app.\n\nEvery chart has a built in default configuration for tooltips, or other options (sample https://github.com/railsjazz/rails_charts/blob/main/lib/rails_charts/line_chart.rb#L64-L75). This is just to simplify usage of this gem. In the future the plan is to have it configured in initializer.\n\n### Area Chart\n\n![Area Chart](docs/area_chart.png)\n\n```ruby\n\u003c%= area_chart User.distinct.pluck(:role).map{|e| {name: e, data: User.where(role: e).group_by_day(:created_at).count} } %\u003e\n```\n\n### Line Chart\n\n![Line Chart](docs/line_chart.png)\n\n```ruby\n\u003c%= line_chart User.group(:age).count, class: 'box',\n  options: {\n    title: {\n      text: \"People count by age\",\n      left: 'center'\n    },\n  }\n%\u003e\n```\n\n### Bar Chart\n\n![Bar Chart](docs/bar_chart.png)\n\n```ruby\n\u003c%= bar_chart User.group(:role).average(:age),\n  class: 'box',\n  theme: 'sakura',\n  options: {\n    series: {\n      barWidth: '50%'\n    },\n    tooltip: {\n      valueFormatter: RailsCharts.js(\"(value) =\u003e '$' + Math.round(value)\")\n    }\n  }\n%\u003e\n```\n\n### Calendar Chart\n\n![Calendar Chart](docs/calendar_chart.png)\n\n```ruby\n\u003c%= calendar_chart Commit.for_calendar_chart,\n  class: 'box',\n  options: {\n    visualMap: {\n      show: true,\n      min: 0,\n      max: 40,\n      orient: 'horizontal'\n    },\n    calendar: [{\n      range: '2021',\n    },]\n  }\n%\u003e\n\n```\n\n### Candlestick Chart\n\n![Candlestick Chart](docs/candlestick_chart.png)\n\n```ruby\n\u003c%= candlestick_chart({\n    '2017-10-24' =\u003e [20, 34, 10, 38],\n    '2017-10-25' =\u003e [40, 35, 30, 50],\n    '2017-10-26' =\u003e [31, 38, 33, 44],\n    '2017-10-27' =\u003e [38, 15, 5, 42]\n  },\n  class: 'box',\n  theme: 'roma',\n  options: {\n    xAxis: {\n      axisTick: {\n        alignWithLabel: true\n      }\n    }\n  })\n%\u003e\n```\n\n### Funnel Chart\n\n![Funnel Chart](docs/funnel_chart.png)\n\n```ruby\n\u003c%= funnel_chart User.get_funnel_sample_data,\n  class: 'box',\n  height: '400px',\n  options: {\n    title: {\n      text: 'Demo',\n      left: 'center'\n    }\n  }\n%\u003e\n```\n\n### Gauge Chart\n\n![Gauge Chart](docs/gauge_chart.png)\n\n```ruby\n\u003c%= gauge_chart User.get_gauge_sample_data,\n  class: 'box',\n  height: '400px',\n  options: {\n    title: {\n      text: 'Demo',\n      left: 'center'\n    }\n  }\n%\u003e\n```\n\n### Parallel Chart\n\n![Parallel Chart](docs/parallel_chart.png)\n\n```ruby\n\u003cdiv class=\"box\"\u003e\n  \u003c%= parallel_chart [\n    [1, 2, 1, \"Ruby\"],\n    [2, 3, 2, \"JavaScript\"],\n    [3, 1, 3, \"C#\"]\n  ], {\n    options: {\n      parallelAxis: [\n        { dim: 0, name: '2019', inverse: true, minInterval: 1, min: 1, nameTextStyle: { fontSize: 16 }, axisLabel: { fontSize: 16 } },\n        { dim: 1, name: '2020', inverse: true, minInterval: 1, min: 1, nameTextStyle: { fontSize: 16 }, axisLabel: { fontSize: 16 } },\n        { dim: 2, name: '2021', inverse: true, minInterval: 1, min: 1, nameTextStyle: { fontSize: 16 }, axisLabel: { fontSize: 16 } },\n        { dim: 3, type: \"category\", name: 'Language', data: [\"Ruby\", \"JavaScript\", \"C#\"], inverse: true, nameTextStyle: { fontSize: 16 }, axisLabel: { fontSize: 14 } },\n      ]\n    }\n  }\n  %\u003e\n\u003c/div\u003e\n```\n\n### Donut Chart\n\n![Donut Chart](docs/donut_chart.png)\n\n```ruby\n\u003c%= donut_chart User.group(:role).count,\n  class: 'box',\n  options: {\n    legend: {\n      bottom: '0'\n    },\n    emphasis: {\n      itemStyle: {\n        shadowBlur: 10,\n        shadowOffsetX: 0,\n        shadowColor: 'rgba(0, 0, 0, 0.5)'\n      }\n    }\n  }\n%\u003e\n```\n\n### Pie Chart\n\n![Pie Chart](docs/pie_chart.png)\n\n```ruby\n\u003c%= pie_chart User.group(:role).count,\n  class: 'box',\n  options: {\n    legend: { orient: 'vertical', left: 'left' }\n  }\n%\u003e\n```\n\n### Radar Chart\n\n![Radar Chart](docs/radar_chart.png)\n\n```ruby\n\u003c%= radar_chart User.get_data_for_radar_chart,\n  class: 'box',\n  options: {\n    legend: {\n      data: ['Average Salaries', 'Maximum Salary'],\n      orient: 'vertical',\n      left: '20%'\n    }\n  }\n%\u003e\n```\n\n### Sankey Chart\n\n![Sankey Chart](docs/sankey_chart.png)\n\n```ruby\n\u003c%= sankey_chart({\n    data: [\n      {name: 'Ruby'}, {name: 'HTML'}, {name: 'JS'}, {name: 'Good'}, {name: 'Bad'}, {name: 'CSS'}, {name: 'PHP'}, {name: 'Frontend'}, {name: 'Backend'}\n    ],\n    links: [\n      {\n        source: 'Ruby',\n        target: 'Good',\n        value: 1\n      },\n      {\n        source: 'HTML',\n        target: 'Good',\n        value: 1\n      },\n      {\n        source: 'JS',\n        target: 'Good',\n        value: 1\n      },\n      {\n        source: 'CSS',\n        target: 'Good',\n        value: 1\n      },\n      {\n        source: 'PHP',\n        target: 'Bad',\n        value: 1\n      },\n      {\n        source: 'Good',\n        target: 'Backend',\n        value: 1\n      },\n      {\n        source: 'Good',\n        target: 'Frontend',\n        value: 3\n      },\n      {\n        source: 'Bad',\n        target: 'Backend',\n        value: 1\n      },\n    ]\n  }, {\n    options: {\n\n    }\n  })\n  %\u003e\n```\n\n### Scatter Chart\n\n![Scatter Chart](docs/scatter_chart.png)\n\n```ruby\n\u003c%= scatter_chart [\n    { name: 'John', data: User.random_scatter_chart(500, 200) },\n    { name: 'Bob', data: User.random_scatter_chart(500, 1000) },\n  ],\n  {\n    class: 'box',\n    options: {\n      xAxis: {\n        name: 'Distance'\n      },\n      yAxis: {\n        name: 'Sales'\n      },\n      legend: {\n        data: [\n          {name: 'John'},\n          {name: 'Bob'},\n        ]\n      },\n    },\n  }\n%\u003e\n```\n\n### Stacked bar Chart\n\n![Stacked bar Chart](docs/stacked_bar_chart.png)\n\n```ruby\n\u003c%= stacked_bar_chart [\n    { name: 'high priority', data: Account.group_by_month(:created_at, format: \"%b %Y\").count },\n    { name: 'low priority', data: Account.group_by_month(:created_at, format: \"%b %Y\").count }\n  ],\n  {\n    options: {\n      title: {\n        text: \"Popular vs Unpopular\"\n      },\n    },\n    class: 'box',\n    vertical: true\n  }\n%\u003e\n```\n\n### Custom Chart\n\n![Custom Chart](docs/custom_chart.png)\n\n```ruby\n\u003c%= custom_chart {...raw JS options ...} %\u003e\n```\n\n## Contributing\n\nYou are welcome to contributes. Some open tasks:\n\n- support turbo streams?\n- add more specs\n- add more examples to the dummy app\n- customization, options overides, default values?\n- every \"5sec\" refresh\n- remote data\n- how to access chart from JS\n- better documentation how to specify theme, locale, etc\n- more examples with data structure\n- add github actions\n- add info about initializer and it's configuration\n- specify info about default configs per chart\n- add support for CSP similar to https://github.com/ankane/chartkick/blob/master/lib/chartkick/helper.rb#L55\n- example of how to build multiple-chart charts\n\n### How to upgrade eCharts\n\n- download ZIP file\n- unpack it\n- replace files in `app/assets/javascripts/echarts.min.js` and other related files inside echarts folder (from root folder of unpacked ZIP file).\n\n### Development and testing\n\n`test/dummy/bin/rails s` - to start dummy app.\n\n`rspec` - to run specs.\n\nPrepare test data:\n\n`rails c`\n\n```ruby\nData.populate\n```\n\n## License\n\nThe gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).\n\nGem is using https://echarts.apache.org/ to build charts.\n\n[\u003cimg src=\"https://github.com/igorkasyanchuk/rails_time_travel/blob/main/docs/more_gems.png?raw=true\"\n/\u003e](https://www.railsjazz.com/?utm_source=github\u0026utm_medium=bottom\u0026utm_campaign=rails_charts)\n\n[![\"Buy Me A Coffee\"](https://github.com/igorkasyanchuk/get-smart/blob/main/docs/snapshot-bmc-button.png?raw=true)](https://buymeacoffee.com/igorkasyanchuk)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frailsjazz%2Frails_charts","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frailsjazz%2Frails_charts","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frailsjazz%2Frails_charts/lists"}