Advanced usage

Data sources

A deep dive into how ODF-Report resolves values from your data.


Two contexts

Values are resolved differently depending on context:

  • Report level — you provide the value directly (a string, number, etc.)
  • Inside tables/sections — values are extracted from each collection item

Static values (report level)

At the report level, the second argument to add_field is used as-is:

report = ODFReport::Report.new("template.odt") do |r|
  r.add_field :title, "Monthly Report"
  r.add_field :date, Date.today.to_s
end

Symbol — method call

Pass a symbol to call that method on each collection item:

r.add_table("USERS", @users) do |t|
  t.add_column(:name, :full_name)   # calls item.full_name
  t.add_column(:email)              # calls item.email (name used as method)
end

When you only pass one argument (like :email), the field name is also used as the method name.


Array — method chain

Pass an array of symbols to chain method calls:

r.add_table("USERS", @users) do |t|
  t.add_column(:company_name, [:company, :name])
  # calls item.company.name
end

You can also include method-with-argument hashes in the chain:

t.add_column(:formatted, [:name, { truncate: 20 }])
# calls item.name.truncate(20)

Hash — method with argument

Pass a hash to call a method with an argument:

t.add_column(:name, { full_name: :upcase })
# calls item.full_name(:upcase)

Block — custom transform

Pass a block for full control over the value:

r.add_field(:status) { |item| item.active? ? "Active" : "Inactive" }

r.add_table("ITEMS", @items) do |t|
  t.add_column(:price) { |item| format("$%.2f", item.price) }
  t.add_column(:description) { |item| "==> #{item.description}" }
end

The block receives the current record and should return the replacement value.


Hash records

When your collection contains hashes instead of objects, values are looked up by key. The lookup tries multiple key formats:

@users = [
  { name: "Alice", email: "alice@example.com" },
  { name: "Bob", email: "bob@example.com" },
]

r.add_table("USERS", @users) do |t|
  t.add_column(:name)    # looks up :name, "name", "NAME", or :name
  t.add_column(:email)
end

The lookup order is: the original key, lowercase string, uppercase string, then lowercase symbol.


Collection references in sections

Inside a section, when you add a table or nested section, you pass a symbol instead of an array. This symbol is called as a method on each section item:

r.add_section("SC_INVOICE", @invoices) do |s|
  # :items calls invoice.items to get the table collection
  s.add_table("TB_ITEMS", :items) do |t|
    t.add_column(:product_name)
  end

  # :notes calls invoice.notes to get the nested section collection
  s.add_section("SUB_NOTES", :notes) do |s1|
    s1.add_field(:title)
  end
end

This is how ODF-Report connects nested data: each level resolves its collection from the parent item.

Previous
Images