[Note: parts of this message were removed to make it a legal post.]
On Fri, Jan 15, 2010 at 8:42 AM, Dave Birch <thisisdaveb@gmail.com> wrote:
> To give you a bit of background to this - I've got a "macro" that is
> generating a bunch of reports. The reports contain lines like "the
> number of people in this group are X and they have spent a total of Y on
> your product this year". The problem is, I can't substitute X and Y for
> their real values at the time the macro runs, because I don't know what
> filters the user will apply when viewing the reports. So I need a way
> to do the calculations and substitute in the values when the user views
> the report, and to recalculate these each time the user changes the
> filter (e.g. show me only people older than 30).
>
> So unless I'm missing something, I can't keep a live object.
>
> It's a rails app, and the controller will be pulling together a
> "@results" variable, but will not necessarily know what kinds of stats
> need to be pulled from it. That's why i'd like to be able to do things
> like "the number of people in this group are <code>@results.size</code>
> and they spent <code>@results.collect(&:spend).sum</code> on your
> product this year".
>
>
I don't really see the benefit of storing the template in the database, but
here is what I came up with.
require 'rubygems'
require 'activerecord'
require 'sqlite3'
require 'erb'
# documentation at
http://www.sqlite.org/lang_createtable.html
db = SQLite3:

atabase.new( 'store_and_execute_strings.db' )
db.execute <<-__________________________________________________
CREATE TABLE IF NOT EXISTS reports (
id INTEGER PRIMARY KEY ASC AUTOINCREMENT,
title Text,
template TEXT
);
__________________________________________________
db.execute <<-__________________________________________________
CREATE TABLE IF NOT EXISTS groups (
id INTEGER PRIMARY KEY ASC AUTOINCREMENT,
name STRING
);
__________________________________________________
db.execute <<-__________________________________________________
CREATE TABLE IF NOT EXISTS people (
id INTEGER PRIMARY KEY ASC AUTOINCREMENT,
group_id INTEGER,
money_spent DOUBLE,
age INTEGER
);
__________________________________________________
# documentation at
http://api.rubyonrails.org/classes/A...cord/Base.html
# for other (better, depending on your needs) documentation, see
http://guides.rubyonrails.org/active..._querying.html
#
http://guides.rubyonrails.org/association_basics.html
#
http://guides.rubyonrails.org/active...callbacks.html
ActiveRecord::Base.establish_connection :adapter =>
'sqlite3' ,
:host =>
'localhost' ,
:database =>
'store_and_execute_strings.db' ,
:username =>
'root' ,

assword => ''
class Report < ActiveRecord::Base
def generate( &init )
dup.instance_eval {
instance_eval &init if init
ERB.new( template , 0 , "%<>" ).result( binding )
}
end
end
class Group < ActiveRecord::Base
has_many

eople
end
class Person < ActiveRecord::Base
belongs_to :group
end
# here is an example, as I understand your criteria
text_for_report = "the number of people in this group are <%= @people.length
%> and they have spent " \
"a total of $<%= @people.inject(0) { |sum,person|
sum+person.money_spent.to_f } %> " \
"on your product this year"
Report.new( :template => text_for_report , :title => 'Customer Summary'
).save
doctors = Group.new :name => 'doctors'
doctors.save
(1..10).each do |num|
money , age = num , 20+num*5
doctors.people.build( :money_spent => money , :age => age ).save
end
customer_summary = Report.find_by_title 'Customer Summary'
puts customer_summary.generate { @people =
doctors.people }
puts customer_summary.generate { @people = doctors.people.all :conditions =>
'money_spent <= 5' }
puts customer_summary.generate { @people = doctors.people.all :conditions =>
'age < 40' }