# Binding scope

**URL:** <https://www.ruby-forum.com/t/binding-scope/181483>\
**Category:** Ruby\
**Created:** [January 12, 2010, 4:57pm UTC](https://www.ruby-forum.com/t/binding-scope/181483 "2010-01-12T16:57:45Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![daz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/87869e/32.png) [@daz](https://www.ruby-forum.com/u/daz)\
**Post date:** [January 12, 2010, 4:57pm UTC](https://www.ruby-forum.com/t/binding-scope/181483/1 "2010-01-12T16:57:45Z")

</div>

Hi,

I’m trying to implement a simple parser and quite likely going about it  
the wrong way.

I would like to be able to include a bit of ruby code in a string, which  
is saved to a field in a database. When the string is retrieve from the  
database at a later stage, I want to parse it for code and evaluate the  
code, substituting the result value into the string.

I’ve been trying to do something like this:

module Substitutable  
@other\_word = “other word”  
proc = Proc.new{}  
String.class\_eval do  
define\_method :to\_s do  
self.gsub(/`(.?)</code>/) do |match|
code = match.scan(/(.)</code>/).flatten.first
eval(code, proc.binding)
end
end
end
end`

# If I then create a class and include Substitutable, I get the

following output

class Tester

include Substitutable

def say  
@word = “hello”  
‘`@other_word`’.to\_s # =\> “other word”  
‘`@word`’.to\_s # =\> “”  
‘`“hard coded word”`’.to\_s # =\> “hard coded word”  
end  
end

Tester.new.say

So I know that conceptually passing the a proc to the eval method does  
enable me to set an instance variable out of the scope of the new to\_s  
method. But I cannot work out how to get the scope of the class within  
which Substitutable has been "include"d. I’ve tried various things  
like…

a) creating an “proc” method within the class that returns a proc object  
b) creating a “@proc” instance variable within the class

…but with no luck.

Is what I’m trying to do possible?

Thanks very much in advance…

Dave

---

<div class="post-metadata">

**Author:** ![daz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/87869e/32.png) [@daz](https://www.ruby-forum.com/u/daz)\
**Post date:** [January 15, 2010, 2:21pm UTC](https://www.ruby-forum.com/t/binding-scope/181483/2 "2010-01-15T14:21:51Z")

</div>

Hi,

Thought I’d try one poke to see if I could resurrect this. I’m still  
stumped on how to solve this.

Thanks in advance.

Regards,  
Dave

---

<div class="post-metadata">

**Author:** ![daz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/87869e/32.png) [@daz](https://www.ruby-forum.com/u/daz)\
**Post date:** [January 15, 2010, 3:10pm UTC](https://www.ruby-forum.com/t/binding-scope/181483/3 "2010-01-15T15:10:16Z")

</div>

Dave B. wrote:

> Hi,
> 
> I’m trying to implement a simple parser and quite likely going about it  
> the wrong way.
> 
> I would like to be able to include a bit of ruby code in a string, which  
> is saved to a field in a database. When the string is retrieve from the  
> database at a later stage, I want to parse it for code and evaluate the  
> code, substituting the result value into the string.

You are aware of the serious security problems with this, right?

[…]

> But I cannot work out how to get the scope of the class within  
> which Substitutable has been "include"d.

Perhaps you should use the Module#included callback to register it.

Best,  
–Â  
Marnen Laibow-Koser  
[http://www.marnen.org](http://www.marnen.org)  
removed\_email\_address@domain.invalid

---

<div class="post-metadata">

**Author:** ![daz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/87869e/32.png) [@daz](https://www.ruby-forum.com/u/daz)\
**Post date:** [January 15, 2010, 3:21pm UTC](https://www.ruby-forum.com/t/binding-scope/181483/4 "2010-01-15T15:21:20Z")

</div>

Hi Marnen

Thanks very much for the reponse.

Marnen Laibow-Koser wrote:

> Dave B. wrote:

> You are aware of the serious security problems with this, right?

Yes, this isn’t a public-facing site, and there will be no front-end  
access to the database that will generate and store the code.

> […]
> 
> > But I cannot work out how to get the scope of the class within  
> > which Substitutable has been "include"d.
> 
> Perhaps you should use the Module#included callback to register it.

I will look at this - thanks again for the tip.

Regards,  
Dave

> Best,  
> –Â  
> Marnen Laibow-Koser  
> [http://www.marnen.org](http://www.marnen.org)  
> removed\_email\_address@domain.invalid

---

<div class="post-metadata">

**Author:** ![daz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/87869e/32.png) [@daz](https://www.ruby-forum.com/u/daz)\
**Post date:** [January 15, 2010, 3:42pm UTC](https://www.ruby-forum.com/t/binding-scope/181483/5 "2010-01-15T15:42:14Z")

</div>

Marnen Laibow-Koser wrote:

> Dave B. wrote:
> 
> > Hi Marnen
> > 
> > Thanks very much for the reponse.
> > 
> > Marnen Laibow-Koser wrote:
> > 
> > > Dave B. wrote:
> > 
> > > You are aware of the serious security problems with this, right?
> > 
> > Yes, this isn’t a public-facing site, and there will be no front-end  
> > access to the database that will generate and store the code.
> 
> Then you shouldn’t need to do this in the first place. If there’s no  
> frontend access to the DB, presumably that means that the app itself is  
> generating the code. If so, then it can keep it as a method in a live  
> object rather than writing it to the database and opening up a security  
> hole.

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 `@results.size`  
and they spent `@results.collect(&:spend).sum` on your  
product this year”.

Doees this make sense?

> > > […]
> > > 
> > > > But I cannot work out how to get the scope of the class within  
> > > > which Substitutable has been "include"d.
> > > 
> > > Perhaps you should use the Module#included callback to register it.
> > 
> > I will look at this - thanks again for the tip.
> > 
> > Regards,  
> > Dave
> > 
> > > Best,  
> > > –Â  
> > > Marnen Laibow-Koser  
> > > [http://www.marnen.org](http://www.marnen.org)  
> > > removed\_email\_address@domain.invalid
> 
> Best,  
> –Â  
> Marnen Laibow-Koser  
> [http://www.marnen.org](http://www.marnen.org)  
> removed\_email\_address@domain.invalid

---

<div class="post-metadata">

**Author:** ![daz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/87869e/32.png) [@daz](https://www.ruby-forum.com/u/daz)\
**Post date:** [January 15, 2010, 6:30pm UTC](https://www.ruby-forum.com/t/binding-scope/181483/6 "2010-01-15T18:30:37Z")

</div>

On 2010-01-15, Dave B. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) 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).

Check with a rails group, but I’m pretty sure you’ll find that you can,  
in fact, do this natively in rails without the security hole.

-s

---

<div class="post-metadata">

**Author:** ![daz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/87869e/32.png) [@daz](https://www.ruby-forum.com/u/daz)\
**Post date:** [January 15, 2010, 3:31pm UTC](https://www.ruby-forum.com/t/binding-scope/181483/7 "2010-01-15T15:31:32Z")

</div>

Dave B. wrote:

> Hi Marnen
> 
> Thanks very much for the reponse.
> 
> Marnen Laibow-Koser wrote:
> 
> > Dave B. wrote:
> 
> > You are aware of the serious security problems with this, right?
> 
> Yes, this isn’t a public-facing site, and there will be no front-end  
> access to the database that will generate and store the code.

Then you shouldn’t need to do this in the first place. If there’s no  
frontend access to the DB, presumably that means that the app itself is  
generating the code. If so, then it can keep it as a method in a live  
object rather than writing it to the database and opening up a security  
hole.

> > […]
> > 
> > > But I cannot work out how to get the scope of the class within  
> > > which Substitutable has been "include"d.
> > 
> > Perhaps you should use the Module#included callback to register it.
> 
> I will look at this - thanks again for the tip.
> 
> Regards,  
> Dave
> 
> > Best,  
> > –Â  
> > Marnen Laibow-Koser  
> > [http://www.marnen.org](http://www.marnen.org)  
> > removed\_email\_address@domain.invalid

Best,  
–Â  
Marnen Laibow-Koser  
[http://www.marnen.org](http://www.marnen.org)  
removed\_email\_address@domain.invalid

---

<div class="post-metadata">

**Author:** ![daz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/87869e/32.png) [@daz](https://www.ruby-forum.com/u/daz)\
**Post date:** [January 15, 2010, 6:54pm UTC](https://www.ruby-forum.com/t/binding-scope/181483/8 "2010-01-15T18:54:02Z")

</div>

On Fri, Jan 15, 2010 at 8:42 AM, Dave B. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> 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 `@results.size`  
> and they spent `@results.collect(&:spend).sum` 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](http://www.sqlite.org/lang_createtable.html)

db = SQLite3::Database.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

> **[ActiveRecord::Base](https://api.rubyonrails.org/classes/ActiveRecord/Base.html)**
>
> Active Record Active Record objects don't specify their attributes directly, but rather infer them from the table definition with which they're linked.

# for other (better, depending on your needs) documentation, see

> **[Active Record Query Interface — Ruby on Rails Guides](https://guides.rubyonrails.org/active_record_querying.html)**
>
> Active Record Query InterfaceThis guide covers different ways to retrieve data from the database using Active Record.After reading this guide, you will know: How to find records using a variety of methods and conditions. How to specify the order,...

# 

> **[Active Record Associations — Ruby on Rails Guides](https://guides.rubyonrails.org/association_basics.html)**
>
> Active Record AssociationsThis guide covers the association features of Active Record.After reading this guide, you will know: How to declare associations between Active Record models. How to understand the various types of Active Record...

# 

[http://guides.rubyonrails.org/activerecord\_validations\_callbacks.html](http://guides.rubyonrails.org/activerecord_validations_callbacks.html)  
ActiveRecord::Base.establish\_connection :adapter =\>  
‘sqlite3’ ,  
:host =\>  
‘localhost’ ,  
:database =\>  
‘store\_and\_execute\_strings.db’ ,  
:username =\>  
‘root’ ,  
:password =\> ‘’

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 :people  
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’ }

---

<div class="post-metadata">

**Author:** ![daz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/87869e/32.png) [@daz](https://www.ruby-forum.com/u/daz)\
**Post date:** [January 15, 2010, 7:09pm UTC](https://www.ruby-forum.com/t/binding-scope/181483/9 "2010-01-15T19:09:06Z")

</div>

Josh, thanks VERY much for the response. I’m going to digest it and  
will let you know once I’ve got it working.

Have a good weekend.

Cheers,  
Dave

Josh C. wrote:

> Hmm, formatting looks really bad up on my email, here is a pastie for it  
> [http://pastie.org/private/taieshtr0nwhnv1unkrjq](http://pastie.org/private/taieshtr0nwhnv1unkrjq)

---

<div class="post-metadata">

**Author:** ![daz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/87869e/32.png) [@daz](https://www.ruby-forum.com/u/daz)\
**Post date:** [January 15, 2010, 6:57pm UTC](https://www.ruby-forum.com/t/binding-scope/181483/10 "2010-01-15T18:57:32Z")

</div>

Hmm, formatting looks really bad up on my email, here is a pastie for it  
[http://pastie.org/private/taieshtr0nwhnv1unkrjq](http://pastie.org/private/taieshtr0nwhnv1unkrjq)

---

<div class="post-metadata">

**Author:** ![daz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/87869e/32.png) [@daz](https://www.ruby-forum.com/u/daz)\
**Post date:** [January 16, 2010, 1:25am UTC](https://www.ruby-forum.com/t/binding-scope/181483/11 "2010-01-16T01:25:04Z")

</div>

Dave B. wrote:

> Josh, thanks VERY much for the response. I’m going to digest it and  
> will let you know once I’ve got it working

No. Better to go for a solution without the security hole. It should be  
possible, but ask on the Rails list instead.

> Have a good weekend.
> 
> Cheers,  
> Dave
> 
> Josh C. wrote:
> 
> > Hmm, formatting looks really bad up on my email, here is a pastie for it  
> > [http://pastie.org/private/taieshtr0nwhnv1unkrjq](http://pastie.org/private/taieshtr0nwhnv1unkrjq)

Best,  
–Â  
Marnen Laibow-Koser  
[http://www.marnen.org](http://www.marnen.org)  
removed\_email\_address@domain.invalid
