![Oracle Drags Its Feet in the JavaScript Trademark Dispute](https://cdn.sanity.io/images/cgdhsj6q/production/919c3b22c24f93884c548d60cbb338e819ff2435-1024x1024.webp?w=400&fit=max&auto=format)
Security News
Oracle Drags Its Feet in the JavaScript Trademark Dispute
Oracle seeks to dismiss fraud claims in the JavaScript trademark dispute, delaying the case and avoiding questions about its right to the name.
All Axlsx related gems have been forked or moved to a community organization: http://github.com/caxlsx
The gems will be released as is as a starting point to allow releases of other gems that depend on these gems. Submit issues as usual.
Please consider helping develop and test these gems.
In your Gemfile:
gem 'axlsx_rails'
See previous installations if needed.
render_to_string
to render a mail attachment.Axlsx-Rails provides a renderer and a template handler. It adds the :xlsx
format and parses .xlsx.axlsx
templates. This lets you take all the Axlsx code out of your controller or model and place it inside the template, where view code belongs! See this blog post for a more complete walkthrough.
To use Axlsx-Rails set your instance variables in your controller and configure the response if needed:
class ButtonController < ApplicationController
def action_name
@buttons = Button.all
respond_to do |format|
format.xlsx
end
end
end
Create the template with the .xlsx.axlsx
extension (action_name.xlsx.axlsx
for example.) Watch out for typos! In the template, use xlsx_package variable to create your spreadsheet:
wb = xlsx_package.workbook
wb.add_worksheet(name: "Buttons") do |sheet|
@buttons.each do |button|
sheet.add_row [button.name, button.category, button.price]
end
end
This is where you place all your Axlsx specific markup. Add worksheets, fill content, merge cells, add styles. See the Axlsx examples page to see what you can do.
Remember, like in erb
templates, view helpers are available to use the .xlsx.axlsx
template.
That's it. Call your action and your spreadsheet will be delivered.
You can call render in any of the following ways:
# rendered, no disposition/filename header
render 'buttons'
# rendered from another controller, no disposition/filename header
render 'featured/latest'
# template and filename of 'buttons'
render xlsx: 'buttons'
# template from another controller, filename of 'latest_buttons'
render xlsx: 'latest_buttons', template: 'featured/latest'
To specify a disposition (such as inline
so the spreadsheet is opened inside the browser), use the disposition
option:
render xlsx: "buttons", disposition: 'inline'
If render xlsx:
is called, the disposition defaults to attachment
.
If Rails calls Axlsx through default channels (because you use format.xlsx {}
for example) you must set the filename using the response header:
format.xlsx {
response.headers['Content-Disposition'] = 'attachment; filename="my_new_filename.xlsx"'
}
If you use render xlsx:
the gem will try to guess the file name:
# filename of 'buttons'
render xlsx: 'buttons'
# filename of 'latest_buttons'
render xlsx: 'latest_buttons', template: 'featured/latest'
If that fails, pass the :filename
parameter:
render xlsx: "action_or_template", filename: "my_new_filename.xlsx"
If you use acts_as_xlsx, configure the active record normally, but specify the package in the template:
User.to_xlsx package: xlsx_package, (other options)
Note: As of 4/1/2014 Acts As Xlsx is not compatible with Rails 4.1, and generates a warning on 4.0. You may use my patched fork until it is remedied.
Axlsx provides three options for initializing a spreadsheet:
To pass these to the new package, pass them to render :xlsx
or pass them as local variables.
For example, to set the author name, pass the :xlsx_author
parameter to render :xlsx
or as a local variable:
render xlsx: "index", xlsx_author: "Elmer Fudd"
render "index", locals: {xlsx_author: "Elmer Fudd"}
Other examples:
render xlsx: "index", xlsx_created_at: 3.days.ago
render "index", locals: {xlsx_use_shared_strings: true}
Partials work as expected, but you must pass in relevant spreadsheet variables:
wb = xlsx_package.workbook
render :partial => 'cover_sheet', :locals => {:wb => wb}
wb.add_worksheet(name: "Content") do |sheet|
sheet.add_row ['Content']
end
With the partial simply using the passed variables:
wb.add_worksheet(name: "Cover Sheet") do |sheet|
sheet.add_row ['Cover', 'Sheet']
end
To use an xlsx template to render a mail attachment, use the following syntax:
class UserMailer < ActionMailer::Base
def export(users)
xlsx = render_to_string layout: false, handlers: [:axlsx], formats: [:xlsx], template: "users/export", locals: {users: users}
attachment = Base64.encode64(xlsx)
attachments["Users.xlsx"] = {mime_type: Mime[:xlsx], content: attachment, encoding: 'base64'}
# For rails 4 use Mime::XLSX
# attachments["Users.xlsx"] = {mime_type: Mime::XLSX, content: attachment, encoding: 'base64'}
# self.instance_variable_set(:@_lookup_context, nil) # If attachments are rendered as content, try this and open an issue
...
end
end
:xlsx
format you do not need to specify formats
or handlers
.users/export
) can refer to only one file (the xlsx.axlsx template), you do not need to specify handlers
, provided the formats
includes :xlsx
.To generate a template within a script, you need to instantiate an ActionView context. Here are two gists showing how to perform this:
There is no built-in way to test your resulting workbooks / templates. But here is a piece of code that may help you to find a way.
RSpec.shared_context 'axlsx' do
# all xlsx specs describe must be normalized
# "folder/view_name.xlsx.axlsx"
# allow to infer the template path
template_name = description
let(:template_path) do
['app', 'views', template_name]
end
# This helper will be used in tests
def render_template(locals = {})
axlsx_binding = Kernel.binding
locals.each do |key, value|
axlsx_binding.local_variable_set key, value
end
# define a default workbook and a default sheet useful when testing partial in isolation
wb = Axlsx::Package.new.workbook
axlsx_binding.local_variable_set(:wb, wb)
axlsx_binding.local_variable_set(:sheet, wb.add_worksheet)
# mimics an ActionView::Template class, presenting a 'source' method
# to retrieve the content of the template
filename = Rails.root.join(*template_path).to_s
source = Struct.new(:source).new(File.read(filename))
axlsx_binding.eval(ActionView::Template::Handlers::AxlsxBuilder.new.call(source), filename)
axlsx_binding.local_variable_get(:wb)
end
end
require 'spec_helper'
require 'helpers/axlsx_context'
describe 'shared/_total_request.xlsx.axlsx' do
include_context 'axlsx'
before :each do
# all the instance variables here are the one used in 'shared/_total_request.xlsx.axlsx'
@widget = mock_model(Widget, name: 'My widget')
@message_counts = Struct.new(:count_all, :positives, :negatives, :neutrals).new(42, 23, 15, 25)
end
it 'has a title line mentioning the widget' do
wb = render_template
sheet = wb.sheet_by_name('Réf. Requête')
expect(sheet).to have_header_cells ['My widget : Messages de la requête']
end
it 'exports the message counts' do
wb = render_template
sheet = wb.sheet_by_name('Réf. Requête')
expect(sheet).to have_cells(['Toutes tonalités', 'Tonalité positive', 'Tonalité négative', 'Tonalité neutre']).in_row(2)
expect(sheet).to have_cells([42, 23, 15, 25]).in_row(3)
end
end
# encoding: UTF-8
require 'rspec/expectations'
module XslsMatchers
RSpec::Matchers.define :have_header_cells do |cell_values|
match do |worksheet|
worksheet.rows[0].cells.map(&:value) == cell_values
end
failure_message do |actual|
"Expected #{actual.rows[0].cells.map(&:value)} to be #{expected}"
end
end
RSpec::Matchers.define :have_cells do |expected|
match do |worksheet|
worksheet.rows[@index].cells.map(&:value) == expected
end
chain :in_row do |index|
@index = index
end
failure_message do |actual|
"Expected #{actual.rows[@index].cells.map(&:value)} to include #{expected} at row #{@index}."
end
end
end
It is easy to get the spelling wrong in the extension name, the format.xlsx statement, or in a render call. Here are some possibilities:
.xlsx.axlsx
.uninitialized constant Mime::XSLX
you have used format.xslx
instead of format.xlsx
, or something similar.If you are having problems with rendering a template and attaching it to a template, try a few options:
self.instance_variable_set(:@_lookup_context, nil)
. If you must do this, please open an issue.encoding: 'base64'
with the attachment:class UserMailer < ActionMailer::Base
def export(users)
xlsx = render_to_string handlers: [:axlsx], formats: [:xlsx], template: "users/export", locals: {users: users}
attachments["Users.xlsx"] = {mime_type: Mime[:xlsx], content: xlsx, encoding: 'base64'}
# For Rails 4 use Mime::XLSX
# attachments["Users.xlsx"] = {mime_type: Mime::XLSX, content: xlsx, encoding: 'base64'}
# self.instance_variable_set(:@_lookup_context, nil) # If attachments are rendered as content, try this and open an issue
...
end
end
If you get these errors, please open an issue and share code so the bug can be isolated. Or comment on issue #29 or #25.
Both these errors appear to be caused by Rails applying a layout to the template. Passing layout: false
to render :xlsx
should fix this issue. Version 0.5.0 attempts to fix this issue.
If you get this error, please open an issue and share code so the bug can be isolated.
Before Rails 4.2 you could call:
render xlsx: "users/index"
And axlsx_rails could adjust the paths and make sure the template was loaded from the right directory. This is no longer possible because the paths are cached between requests for a given controller. As a result, to display a template in another directory you must use the :template
parameter (which is normal Rails behavior anyway):
render xlsx: "index", template: "users/index"
If the request format matches you should be able to call:
render "users/index"
This is a breaking change if you have the old syntax!
If you are using turbolinks, you may need to disable turbolinks when you link to your spreadsheet:
# turbolinks 5:
link_to 'Download spreadsheet', path_to_sheet, data: {turbolinks: false}
If you are having problems, try to isolate the issue. Use the console or a script to make sure your data is good. Then create the spreadsheet line by line without Axlsx-Rails to see if you are having Axlsx problems. If you can manually create the spreadsheet, create an issue and we will work it out.
In your Gemfile:
gem 'rubyzip', '>= 1.2.1'
gem 'axlsx', git: 'https://github.com/randym/axlsx.git', ref: 'c8ac844'
gem 'axlsx_rails'
If rubyzip 1.0.0
is needed:
gem 'rubyzip', '= 1.0.0'
gem 'axlsx', '= 2.0.1'
gem 'axlsx_rails'
If rubyzip >= 1.1.0
is needed:
gem 'rubyzip', '~> 1.1.0'
gem 'axlsx', '2.1.0.pre'
gem 'axlsx_rails'
Many thanks to contributors:
Say thanks for Axlsx-Rails by donating! It makes it easier for me to provide to open source:
September 5, 2019: 0.5.3 release
May 1st, 2018: 0.5.2 release
March 29th, 2017: 0.5.1 release
July 26st, 2016: 0.5.0 release
July 13th, 2015: 0.4.0 release
November 20th, 2014: 0.3.0 release
render xlsx: 'another/directory'
)September 4, 2014: 0.2.1 release
April 9, 2014: 0.2.0 release
October 11, 2013
October 4, 2013
July 25, 2013
January 18, 2013: 0.1.4 release
December 6, 2012: 0.1.3 release
July 25, 2012: 0.1.2 release
July 19, 2012: 0.1.1 release
July 17, 2012: 0.1.0 release
July 12, 2012: 0.0.1 release
FAQs
Unknown package
We found that axlsx_rails demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Oracle seeks to dismiss fraud claims in the JavaScript trademark dispute, delaying the case and avoiding questions about its right to the name.
Security News
The Linux Foundation is warning open source developers that compliance with global sanctions is mandatory, highlighting legal risks and restrictions on contributions.
Security News
Maven Central now validates Sigstore signatures, making it easier for developers to verify the provenance of Java packages.