Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade to latest Rails 4 release #1

Merged
merged 17 commits into from Mar 14, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -4,5 +4,6 @@ log/*.log
pkg/
*.gem
Gemfile.lock
spec/gemfiles/*.lock
.ruby-version
.ruby-gemset
16 changes: 11 additions & 5 deletions .travis.yml
@@ -1,8 +1,14 @@
language: ruby
cache: bundler
bundler_args: --path ../../vendor/bundle
rvm:
- 2.0.0
- 2.2.2
- 1.9.3
- jruby-head


script: bundle exec rake spec
- jruby
gemfile:
- spec/gemfiles/Gemfile.rails-3.2
- spec/gemfiles/Gemfile.rails-4.0
- spec/gemfiles/Gemfile.rails-4.1
- spec/gemfiles/Gemfile.rails-4.2
- Gemfile
script: bundle exec rspec
149 changes: 149 additions & 0 deletions README.md
@@ -0,0 +1,149 @@
# to_spreadsheet [![Build Status](https://secure.travis-ci.org/glebm/to_spreadsheet.png?branch=master)](http://travis-ci.org/glebm/to_spreadsheet)

to_spreadsheet lets your Rails 3+ app render Excel files using the existing slim/haml/erb/etc views.

Installation
------------

Add it to your Gemfile:
```ruby
gem 'to_spreadsheet'
```

Usage
-----

In the controller:
```ruby
# my_thingies_controller.rb
class MyThingiesController < ApplicationController
respond_to :xls, :html
def index
@my_items = MyItem.all
respond_to do |format|
format.html
format.xlsx { render xlsx: :index, filename: "my_items_doc" }
end
end
end
```

In the view partial:
```haml
# _my_items.haml
%table
%caption My items
%thead
%tr
%td ID
%td Name
%tbody
- my_items.each do |my_item|
%tr
%td.number= my_item.id
%td= my_item.name
%tfoot
%tr
%td(colspan="2") #{my_items.length}
```

In the XLSX view:
```haml
# index.xls.haml
= render 'my_items', my_items: @my_items
```

In the HTML view:
```haml
# index.html.haml
= link_to 'Download spreadsheet', my_items_url(format: :xlsx)
= render 'my_items', my_items: @my_items
```

### Worksheets

Every table in the view will be converted to a separate sheet.
The sheet title will be assigned to the value of the table’s caption element if it exists.

### Formatting

You can define formats in your view file (local to the view) or in the initializer

```ruby
format_xls 'table.my-table' do
workbook use_autowidth: true
sheet orientation: landscape
format 'th', b: true # bold
format 'tbody tr', bg_color: lambda { |row| 'ddffdd' if row.index.odd? }
format 'A3:B10', i: true # italic
format column: 0, width: 35
format 'td.custom', lambda { |cell| modify cell somehow.}
# default value (fallback value when value is blank or 0 for integer / float)
default 'td.price', 10
end
```

For the full list of supported properties head here: http://rubydoc.info/github/randym/axlsx/Axlsx/Styles#add_style-instance_method
In addition, for column formats, Axlsx columnInfo properties are also supported

### Advanced formatting

to_spreadsheet [associates](https://github.com/glebm/to_spreadsheet/blob/master/lib/to_spreadsheet/renderer.rb#L33) HTML nodes with Axlsx objects as follows:

| HTML tag | Axlsx object |
|----------|--------------|
| table | worksheet |
| tr | row |
| td, th | cell |

For example, to directly manipulate a worksheet:
```ruby
format_xls do
format 'table' do |worksheet|
worksheet.add_chart ...
# to get the associated Nokogiri node:
el = context.to_xml_node(worksheet)
end
end
```

### Themes

You can define themes, i.e. blocks of formatting code:
```ruby
ToSpreadsheet.theme :zebra do
format 'tr', bg_color: lambda { |row| 'ddffdd' if row.index.odd? }
end
```

And then use them:
```ruby
format_xls 'table.zebra', ToSpreadsheet.theme(:zebra)
```

### Using along side axlsx-rails
If you are using [axlsx-rails](https://github.com/straydogstudio/axlsx_rails), :xlsx renderer might have already been defined. In that case define a custome renderer using
```ruby
# app/config/application.rb
config.to_spreadsheet.renderer = :html2xlsx
```

And then in controller
```ruby
respond_to do |format|
format.html2xlsx
end
```

### Types

The default theme uses class names on td/th to cast values.
Here is the list of class to type mapping:

| CSS class | Format |
|------------------|--------------------------|
| decimal or float | Decimal |
| num or int | Integer |
| datetime | DateTime (Chronic.parse) |
| date | Date (Date.parse) |
| time | Time (Chronic.parse) |
116 changes: 0 additions & 116 deletions README.textile

This file was deleted.

9 changes: 9 additions & 0 deletions Rakefile
Expand Up @@ -21,3 +21,12 @@ task :write_test_xlsx => :env do
ToSpreadsheet::Renderer.to_package(html).serialize(path)
puts "Written to #{path}"
end

desc "Test all rails versions"
task :test_all_rails do
Dir.glob("./spec/gemfiles/*{[!.lock]}").each do |gemfile|
puts "TESTING WITH #{gemfile}"
system "BUNDLE_GEMFILE=#{gemfile} bundle | grep Installing"
system "BUNDLE_GEMFILE=#{gemfile} bundle exec rspec"
end
end
6 changes: 5 additions & 1 deletion lib/to_spreadsheet.rb
@@ -1,10 +1,13 @@
require 'to_spreadsheet/version'
require 'to_spreadsheet/context'
require 'to_spreadsheet/renderer'
require 'to_spreadsheet/railtie' if defined?(Rails)

module ToSpreadsheet
class << self
def renderer
@renderer ||= :xlsx
end

def theme(name, &formats)
@themes ||= {}
if formats
Expand All @@ -16,5 +19,6 @@ def theme(name, &formats)
end
end

require 'to_spreadsheet/railtie' if defined?(Rails)
require 'to_spreadsheet/themes/default'
ToSpreadsheet::Context.global.format_xls ToSpreadsheet.theme(:default)
20 changes: 15 additions & 5 deletions lib/to_spreadsheet/rails/action_pack_renderers.rb
@@ -1,10 +1,20 @@
require 'active_support'
require 'action_controller/metal/renderers'
require 'action_controller/metal/responder'

# in rails 3.2 it's ActiveSupport::VERSION
# in rails 4.0+ it's ActiveSupport.version (instance of Gem::Version)
if ActiveSupport.respond_to?(:version) && ActiveSupport.version.to_s >= "4.2.0"
# For rails 4.2
require 'action_controller/responder'
else
# For rails 3.2 - rails 4.1
require 'action_controller/metal/responder'
end


# This will let us do thing like `render :xlsx => 'index'`
# This is similar to how Rails internally implements its :json and :xml renderers
ActionController::Renderers.add :xlsx do |template, options|
ActionController::Renderers.add ToSpreadsheet.renderer do |template, options|
filename = options[:filename] || options[:template] || 'data'
xlsx_options = options.merge(layout: false, formats: [:xlsx, :html])
data = ToSpreadsheet::Context.with_context ToSpreadsheet::Context.global.merge(ToSpreadsheet::Context.new) do |context|
Expand All @@ -15,15 +25,15 @@
end
ToSpreadsheet::Renderer.to_data(html, context)
end
send_data data, type: :xlsx, disposition: %(attachment; filename="#{filename}.xlsx")
send_data data, type: ToSpreadsheet.renderer, disposition: %(attachment; filename="#{filename}.xlsx")
end

class ActionController::Responder
# This sets up a default render call for when you do
# respond_to do |format|
# format.xlsx
# end
def to_xlsx
controller.render xlsx: controller.action_name
define_method "to_#{ToSpreadsheet.renderer}" do
controller.render ToSpreadsheet.renderer => controller.action_name
end
end
2 changes: 1 addition & 1 deletion lib/to_spreadsheet/rails/mime_types.rb
@@ -1,2 +1,2 @@
require 'action_dispatch/http/mime_type'
Mime::Type.register "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", :xlsx unless Mime::Type.lookup_by_extension(:xlsx)
Mime::Type.register "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", ToSpreadsheet.renderer unless Mime::Type.lookup_by_extension(ToSpreadsheet.renderer)
13 changes: 9 additions & 4 deletions lib/to_spreadsheet/railtie.rb
@@ -1,10 +1,15 @@
require 'rails/railtie'
require 'to_spreadsheet/rails/mime_types'
require 'to_spreadsheet/rails/action_pack_renderers'
require 'to_spreadsheet/rails/view_helpers'
module ToSpreadsheet
class Railtie < ::Rails::Railtie
initializer "to_spreadsheet.view_helpers" do
config.to_spreadsheet = ActiveSupport::OrderedOptions.new
config.to_spreadsheet.renderer = ToSpreadsheet.renderer

config.after_initialize do |app|
ToSpreadsheet.instance_variable_set("@renderer", app.config.to_spreadsheet.renderer)

require 'to_spreadsheet/rails/action_pack_renderers'
require 'to_spreadsheet/rails/view_helpers'
require 'to_spreadsheet/rails/mime_types'
ActionView::Base.send :include, ToSpreadsheet::Rails::ViewHelpers
end
end
Expand Down