# Models accessing the session

**URL:** <https://www.ruby-forum.com/t/models-accessing-the-session/93513>\
**Category:** Rails\
**Created:** [April 4, 2006, 10:05am UTC](https://www.ruby-forum.com/t/models-accessing-the-session/93513 "2006-04-04T10:05:26Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![kris](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/82dd89/32.png) [@kris](https://www.ruby-forum.com/u/kris)\
**Post date:** [April 4, 2006, 10:05am UTC](https://www.ruby-forum.com/t/models-accessing-the-session/93513/1 "2006-04-04T10:05:26Z")

</div>

Can someone tell if there is a reason models shouldn’t access the  
session?  
Models could easily be made to access the session or some other shared  
persistant data store such as a file or a table.

_This is the problem_, a model needs to know certain information eg. the  
id of the current user. But the model has no idea about anything outside  
of its self, because it can’t access any kind of shared var.

The only way to tell the model is to pass it at creation time, but this  
does not seem very pretty, because its not a case of passing the bit of  
information once and thats it, its set for all models. You have to do it  
every time.

Is there a way I should be looking at this problem within the MCV  
restraints?

---

<div class="post-metadata">

**Author:** ![kris](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/82dd89/32.png) [@kris](https://www.ruby-forum.com/u/kris)\
**Post date:** [April 4, 2006, 10:23am UTC](https://www.ruby-forum.com/t/models-accessing-the-session/93513/2 "2006-04-04T10:23:08Z")

</div>

On Apr 4, 2006, at 10:05, Kris wrote:

> The only way to tell the model is to pass it at creation time, but  
> this  
> does not seem very pretty, because its not a case of passing the  
> bit of  
> information once and thats it, its set for all models. You have to  
> do it  
> every time.

In MVC it is the responsibility of the controller to fetch session  
data and pass it to models through API calls. If the model needs the  
user id, or needs the user itself, its API will require them  
accordingly.

– fxn

---

<div class="post-metadata">

**Author:** ![kris](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/82dd89/32.png) [@kris](https://www.ruby-forum.com/u/kris)\
**Post date:** [April 4, 2006, 11:25am UTC](https://www.ruby-forum.com/t/models-accessing-the-session/93513/3 "2006-04-04T11:25:09Z")

</div>

Xavier N. wrote:

> In MVC it is the responsibility of the controller to fetch session data  
> and pass it to models through API calls. If the model needs the user id,  
> or needs the user itself, its API will require them accordingly.  
> Depending on how strict you’re being, you could say that the model  
> shouldn’t even know about user ids, only user objects, and that the  
> controller is responsible for generating one from the other and passing  
> the user object to the model in the API. That’s more of a stylistic  
> thing, though…

---

<div class="post-metadata">

**Author:** ![kris](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/82dd89/32.png) [@kris](https://www.ruby-forum.com/u/kris)\
**Post date:** [April 4, 2006, 11:33am UTC](https://www.ruby-forum.com/t/models-accessing-the-session/93513/4 "2006-04-04T11:33:43Z")

</div>

Xavier N. wrote:

> On Apr 4, 2006, at 10:05, Kris wrote:
> 
> > The only way to tell the model is to pass it at creation time, but  
> > this  
> > does not seem very pretty, because its not a case of passing the  
> > bit of  
> > information once and thats it, its set for all models. You have to  
> > do it  
> > every time.
> 
> In MVC it is the responsibility of the controller to fetch session  
> data and pass it to models through API calls. If the model needs the  
> user id, or needs the user itself, its API will require them  
> accordingly.
> 
> – fxn

This is what I suspected 🙂 So basically what you are saying is that if  
a model requires the user id you have to pass it eg.

document = Document.new(current\_user.id)

or

document = Document.new  
document.set\_user\_id(current\_user.id)

Would it break MCV to give models access to the session?

Its just that the above example are ok if you are dealing with a few  
models with where the assosiations don’t need to know the same  
information.

document = Document.new  
attachments =  
document.set\_user\_id(current\_user.id).attachments.set\_user\_id(current\_user.id).find(:all)

Quickly it starts to look less nice, and that only passing one  
parameter.

I believe there is a plugin knocking about that adds the current users  
id to a user\_id field… something like this may be adaptable?

---

<div class="post-metadata">

**Author:** ![kris](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/82dd89/32.png) [@kris](https://www.ruby-forum.com/u/kris)\
**Post date:** [April 4, 2006, 2:55pm UTC](https://www.ruby-forum.com/t/models-accessing-the-session/93513/5 "2006-04-04T14:55:43Z")

</div>

On Tue, Apr 04, 2006 at 11:33:43AM +0200, kris wrote:  
} Xavier N. wrote:  
} \> On Apr 4, 2006, at 10:05, Kris wrote:  
} \>\> The only way to tell the model is to pass it at creation time, but  
} \>\> this does not seem very pretty, because its not a case of passing  
the  
} \>\> bit of information once and thats it, its set for all models. You  
have  
} \>\> to do it every time.  
} \>  
} \> In MVC it is the responsibility of the controller to fetch session  
} \> data and pass it to models through API calls. If the model needs the  
} \> user id, or needs the user itself, its API will require them  
} \> accordingly.  
} \>  
} \> – fxn  
}  
} This is what I suspected 🙂 So basically what you are saying is that  
if  
} a model requires the user id you have to pass it eg.  
}  
} document = Document.new(current\_user.id)  
}  
} or  
}  
} document = Document.new  
} document.set\_user\_id(current\_user.id)  
}  
} Would it break MCV to give models access to the session?

Yes. The value of MVC (not MCV, incidentally) is that the lower layers  
do  
not depend on the higher layers. The model code can be completely  
unaware of the the controller code, or even its existence. Likewise, the  
controller code can be completely unaware of the view code. This allows  
tests to be run on the models without the additional complexity of the  
controllers, for example. It also means that any layer can be replaced  
by  
another layer offering the same API to the higher layer(s) and using the  
same API of the lower layer(s). This is good design.

It is perfectly reasonable for the model to be aware of some context,  
but  
it should be made aware through an API called on it, rather than by  
using  
an API of a higher layer. How can you run unit tests on your models if  
your  
model needs access to a controller session? It’s possible, certainly,  
but  
it is a mess.

} Its just that the above example are ok if you are dealing with a few  
} models with where the assosiations don’t need to know the same  
} information.  
}  
} document = Document.new  
} attachments =  
}  
document.set\_user\_id(current\_user.id).attachments.set\_user\_id(current\_user.id).find(:all)  
}  
} Quickly it starts to look less nice, and that only passing one  
} parameter.  
[…]

If you are in such a situation, you probably have a design problem. I  
have  
a situation in which Event models hide or translate some of their  
attributes based on the current user. I have attr\_accessor :wrt in the  
Event model, and I have an \_event partial that sets the wrt variable to  
the  
current user. Since the partial renders each Event, there is only one  
place  
I have to set things. The models don’t need to be aware of the session.

–Greg

---

<div class="post-metadata">

**Author:** ![kris](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/82dd89/32.png) [@kris](https://www.ruby-forum.com/u/kris)\
**Post date:** [April 4, 2006, 3:14pm UTC](https://www.ruby-forum.com/t/models-accessing-the-session/93513/6 "2006-04-04T15:14:24Z")

</div>

#if krisleech /\* Apr 04, 11:33 \*/

> I believe there is a plugin knocking about that adds the current users  
> id to a user\_id field… something like this may be adaptable?

#endif /\* removed\_email\_address@domain.invalid \*/

Have a read through: (or should that be :through ?)  
[http://www.koziarski.net/archives/2005/07/16/environment](http://www.koziarski.net/archives/2005/07/16/environment)

I think that might be of some use to you.

–  
keys: [http://codex.net/gpg.asc](http://codex.net/gpg.asc)

You can never plan the future by the past.  
– Edmund Burke

---

<div class="post-metadata">

**Author:** ![kris](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/82dd89/32.png) [@kris](https://www.ruby-forum.com/u/kris)\
**Post date:** [April 4, 2006, 4:02pm UTC](https://www.ruby-forum.com/t/models-accessing-the-session/93513/7 "2006-04-04T16:02:42Z")

</div>

Kris wrote:

> Can someone tell if there is a reason models shouldn’t access the  
> session?  
> Models could easily be made to access the session or some other shared  
> persistant data store such as a file or a table.
> 
> _This is the problem_, a model needs to know certain information eg. the  
> id of the current user. But the model has no idea about anything outside  
> of its self, because it can’t access any kind of shared var.
> 
> The only way to tell the model is to pass it at creation time, but this  
> does not seem very pretty, because its not a case of passing the bit of  
> information once and thats it, its set for all models. You have to do it  
> every time.
> 
> Is there a way I should be looking at this problem within the MCV  
> restraints?

I solved this problem by using (pseudo code)

def secure  
result = yield  
if result.kind\_of? Array  
result.map { |r| r.set\_visitor(session[:visitor\_id]) }  
else  
result.set\_visitor(session[:visitor\_id])  
end  
result  
end

With this in you can now do :

doc = secure { Document.new }

or

docs = secure { Document.find(:all) }

If you are interested in more in-depth view of my solution ( also  
securing find with scopes) : gaspard AT teti. DOT ch.

---

<div class="post-metadata">

**Author:** ![kris](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/82dd89/32.png) [@kris](https://www.ruby-forum.com/u/kris)\
**Post date:** [April 4, 2006, 5:42pm UTC](https://www.ruby-forum.com/t/models-accessing-the-session/93513/8 "2006-04-04T17:42:13Z")

</div>

On Tue, Apr 04, 2006 at 03:39:35PM +0200, kris wrote:  
[…]  
} \> “It is perfectly reasonable for the model to be aware of some  
context,  
} \> but it should be made aware through an API called on it, rather than  
by  
} \> using an API of a higher layer.”  
}  
} When you say API you mean the public methods?

In a general sense, yes.

} So basically you call a method which sets some internal attribute  
which  
} the model can then refer to. [I guess there is no way to make that } attribute stick so that you dont have to keep setting it each time you } create an instance of a model, like setting a class attribute instead of } an instance attribute?]

That would be a very bad idea. While a particular Rails server (e.g.  
WEBrick) may not have more than one action in progress, you should  
always  
assume that it could. That means that you could have two (or more)  
actions  
being served concurrently for different users, but only one place to  
store  
the user.

} So if I wanted to have models which had a dynamic datasource, say I  
} could choose the table the model was working on, I would give the  
model  
} an attribute called say current\_table\_name. The current\_table\_name  
} attribute would have a default.  
[…]

I am not at all clear on what you are trying to accomplish.

–Greg

---

<div class="post-metadata">

**Author:** ![kris](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/82dd89/32.png) [@kris](https://www.ruby-forum.com/u/kris)\
**Post date:** [April 4, 2006, 3:39pm UTC](https://www.ruby-forum.com/t/models-accessing-the-session/93513/9 "2006-04-04T15:39:35Z")

</div>

Thanks for the reply.

"Yes. The value of MVC (not MCV, incidentally) is that the lower layers

> do not depend on the higher layers. The model code can be completely  
> unaware of the the controller code, or even its existence."

As suspected…

"It is perfectly reasonable for the model to be aware of some context,

> but it should be made aware through an API called on it, rather than by  
> using an API of a higher layer."

When you say API you mean the public methods?  
So basically you call a method which sets some internal attribute which  
the model can then refer to. [I guess there is no way to make that attribute stick so that you dont have to keep setting it each time you create an instance of a model, like setting a class attribute instead of an instance attribute?]

So if I wanted to have models which had a dynamic datasource, say I  
could choose the table the model was working on, I would give the model  
an attribute called say current\_table\_name. The current\_table\_name  
attribute would have a default.

Pseudo Code

class document \<\< AR  
attribute :current\_table\_name, :default =\> ‘document\_’ + Date.now.year  
set\_table\_name :current\_table\_name

# attribute setter

def current\_table\_name=(new\_table\_name)  
set\_table\_name new\_table\_name.to\_sym  
end  
end

Gregory S. wrote:

> On Tue, Apr 04, 2006 at 11:33:43AM +0200, kris wrote:  
> } Xavier N. wrote:  
> } \> On Apr 4, 2006, at 10:05, Kris wrote:  
> } \>\> The only way to tell the model is to pass it at creation time, but  
> } \>\> this does not seem very pretty, because its not a case of passing  
> the  
> } \>\> bit of information once and thats it, its set for all models. You  
> have  
> } \>\> to do it every time.  
> } \>  
> } \> In MVC it is the responsibility of the controller to fetch session  
> } \> data and pass it to models through API calls. If the model needs the  
> } \> user id, or needs the user itself, its API will require them  
> } \> accordingly.  
> } \>  
> } \> – fxn  
> }  
> } This is what I suspected 🙂 So basically what you are saying is that  
> if  
> } a model requires the user id you have to pass it eg.  
> }  
> } document = Document.new(current\_user.id)  
> }  
> } or  
> }  
> } document = Document.new  
> } document.set\_user\_id(current\_user.id)  
> }  
> } Would it break MCV to give models access to the session?
> 
> Yes. The value of MVC (not MCV, incidentally) is that the lower layers  
> do  
> not depend on the higher layers. The model code can be completely  
> unaware of the the controller code, or even its existence. Likewise, the  
> controller code can be completely unaware of the view code. This allows  
> tests to be run on the models without the additional complexity of the  
> controllers, for example. It also means that any layer can be replaced  
> by  
> another layer offering the same API to the higher layer(s) and using the  
> same API of the lower layer(s). This is good design.
> 
> It is perfectly reasonable for the model to be aware of some context,  
> but  
> it should be made aware through an API called on it, rather than by  
> using  
> an API of a higher layer. How can you run unit tests on your models if  
> your  
> model needs access to a controller session? It’s possible, certainly,  
> but  
> it is a mess.
> 
> } Its just that the above example are ok if you are dealing with a few  
> } models with where the assosiations don’t need to know the same  
> } information.  
> }  
> } document = Document.new  
> } attachments =  
> }  
> document.set\_user\_id(current\_user.id).attachments.set\_user\_id(current\_user.id).find(:all)  
> }  
> } Quickly it starts to look less nice, and that only passing one  
> } parameter.  
> […]
> 
> If you are in such a situation, you probably have a design problem. I  
> have  
> a situation in which Event models hide or translate some of their  
> attributes based on the current user. I have attr\_accessor :wrt in the  
> Event model, and I have an \_event partial that sets the wrt variable to  
> the  
> current user. Since the partial renders each Event, there is only one  
> place  
> I have to set things. The models don’t need to be aware of the session.
> 
> –Greg

---

<div class="post-metadata">

**Author:** ![kris](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/82dd89/32.png) [@kris](https://www.ruby-forum.com/u/kris)\
**Post date:** [April 5, 2006, 7:36am UTC](https://www.ruby-forum.com/t/models-accessing-the-session/93513/10 "2006-04-05T07:36:28Z")

</div>

> > document.set\_user\_id(current\_user.id).attachments.set\_user\_id  
> > (current\_user.id).find(:all)  
> > }  
> > } Quickly it starts to look less nice, and that only passing one  
> > } parameter.

You’re not using associations properly here

current\_user.documents.attachments

will likely return the same results as the line you wrote if I  
understand your schema.

When I first started writing OO code, it took me a while to  
convert my functional background into the OO world. Reading  
Aaron Hillegass’s book, Cocoa Programming For Mac OS X, was  
a big help.

If you do it right, you’ll never end up with code looking  
like what you wrote above. Code like that likely means that  
you are doing something wrong.

Good OO should read easily.

–  
– Tom M.

---

<div class="post-metadata">

**Author:** ![kris](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/82dd89/32.png) [@kris](https://www.ruby-forum.com/u/kris)\
**Post date:** [April 8, 2006, 10:17am UTC](https://www.ruby-forum.com/t/models-accessing-the-session/93513/11 "2006-04-08T10:17:44Z")

</div>

I won’t enter in discussion on MVC, because I _do_ need giving session  
to models : I want them to be able to store a  
creation/modification/destroy event in the database, holding _who_ did  
that to them.

My desire for this feature is stronger than perfect MVC compliance. If I  
have problem with testing, well I’ll whip my back.

Quoting Gazoduc :

> I solved this problem by using (pseudo code)
> 
> def secure  
> result = yield  
> if result.kind\_of? Array  
> result.map { |r| r.set\_visitor(session[:visitor\_id]) }  
> else  
> result.set\_visitor(session[:visitor\_id])  
> end  
> result  
> end
> 
> With this in you can now do :
> 
> doc = secure { Document.new }
> 
> or
> 
> docs = secure { Document.find(:all) }

This is a good idea.  
There is no ambiguity on which session in given to the models : the one  
used by the running controller. There is no risk that concurrent  
requests may badly mix data.

However, you did not answer to the problem raised by Kris :

> document = Document.new  
> attachments = document.set\_user\_id(current\_user.id).attachments.set\_user\_id(current\_user.id).find(:all)
> 
> Quickly it starts to look less nice, and that only passing one parameter

Gazoduc, your secure method gives the session to your Documents, but not  
to their members. Like, say, this\_document.writer which _is_ a model,  
and which should be “secured”, too. The “secure” fonction fails doing  
that.

We definitely have a problem here.

- A single instance of a controller class holds the state (the session)  
it wishes to give to models.
- _Thus_ this single controller is responsible for giving this state to  
the models it creates.

Maybe this _thus_ can be taken _granted_.

Damnit, ActiveRecord is responsible for loading many models from a  
single one, which the controller also wish they hold know its state.  
(all the objects created from the belongs\_to, has\_many, etc.  
associations)

So this single controller wishes it could give to _ActiveRecord_ its  
state, hoping ActiveRecord will give to all models objects it will  
create from now on.

But isn’t ActiveRecord shared among several controllers ?  
Is our goal impossible to reach without modifying the whole ActiveRecord  
framework ?

OMG !

BTW, this whole _state_ stuff makes me think this is a binding we want  
to give to models.

---

<div class="post-metadata">

**Author:** ![kris](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/82dd89/32.png) [@kris](https://www.ruby-forum.com/u/kris)\
**Post date:** [April 8, 2006, 11:06am UTC](https://www.ruby-forum.com/t/models-accessing-the-session/93513/12 "2006-04-08T11:06:19Z")

</div>

On Apr 8, 2006, at 10:17, lagroue wrote:

> I won’t enter in discussion on MVC, because I _do_ need giving session  
> to models : I want them to be able to store a  
> creation/modification/destroy event in the database, holding _who_ did  
> that to them.

The updates of relationships are done by AR itself, so looks like you  
need some global magic that sets the user\_id transparently.

I mean, Document.save(user) won’t work because the (has\_many) Authors  
children won’t be passed the user by AR. Without more details, it  
does not sound DRY to manually set the user throughout all the models.

I don’t know whether this may be helpful, but as starting point you  
could have a look at acts\_as\_paranoid and see how it modifies AR to  
deal with a special column in a really transparent way.

– fxn

---

<div class="post-metadata">

**Author:** ![kris](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/82dd89/32.png) [@kris](https://www.ruby-forum.com/u/kris)\
**Post date:** [April 8, 2006, 10:43am UTC](https://www.ruby-forum.com/t/models-accessing-the-session/93513/13 "2006-04-08T10:43:59Z")

</div>

Vincent AE Scott wrote:

> Have a read through: (or should that be :through ?)  
> [http://www.koziarski.net/archives/2005/07/16/environment](http://www.koziarski.net/archives/2005/07/16/environment)
> 
> I think that might be of some use to you.

Well, no : he uses a class attribute, which is not :secure when requests  
are concurrent.

---

<div class="post-metadata">

**Author:** ![kris](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/82dd89/32.png) [@kris](https://www.ruby-forum.com/u/kris)\
**Post date:** [April 8, 2006, 12:09pm UTC](https://www.ruby-forum.com/t/models-accessing-the-session/93513/14 "2006-04-08T12:09:30Z")

</div>

Xavier N. wrote:

> On Apr 8, 2006, at 10:17, lagroue wrote:
> 
> > I won’t enter in discussion on MVC, because I _do_ need giving session  
> > to models : I want them to be able to store a  
> > creation/modification/destroy event in the database, holding _who_ did  
> > that to them.
> 
> I don’t know whether this may be helpful, but as starting point you  
> could have a look at acts\_as\_paranoid and see how it modifies AR to  
> deal with a special column in a really transparent way.

I’ll do. Thanks.  
Here is the message I was writing before I read your advice :

* * *

Another solution, the with\_session controller method :

# PURPOSE

I’d like to write code like :

with\_session do

# inside this block, _ALL_ models know the session.

…  
end

Maybe we’d define the more general with the with\_context controller  
method :

with\_context (object) do

# inside this block, _ALL_ models share the same context object.

…  
end

Typical (scaffold) controller code with session context :

def update  
with\_session do  
@model = Model.find(param[:id])  
if @model.update\_attributes(params[:model])  
redirect\_to :action =\> ‘show’, :id =\> @model.id  
else  
render :action =\> ‘edit’  
end  
end  
end

And maybe the Model uses this session somewhere, maybe in a after\_update  
callback.  
Or the views do. Who knowns. @session is available to all models, and  
that’s the main purpose.

My own purpose is only storing who did update the model, so I’d write :

def update  
@model = Model.find(param[:id])  
if with\_session do @model.update\_attributes(params[:model]) end  
redirect\_to :action =\> ‘show’, :id =\> @model.id  
else  
render :action =\> ‘edit’  
end  
end

That’s the code I’d like to be able to write.  
Now, how to have it work ?

# IMPLEMENTATION

## Controllers implementation

What could this with\_context method look like ?  
It has to be aware of other concurrent controllers running, so it has to  
look like :

module ContextController

# to be included in Controller classes

# the general with\_context method

def with\_context (context)  
(context) do  
yield  
end  
end

# the particular with\_session

def with\_session  
with\_context(@session) do yield end  
end  
end

Say we let ActiveRecord::Base be responsible of the synchronization :

module ContextController  
def with\_context(context)  
ActiveRecord::Base.with\_context(context) do  
yield  
end  
end  
def with\_session  
with\_context(@session) do yield end  
end  
end

Now we have to define ActiveRecord::Base::with\_context :

## ActiveRecord implementation

class ActiveRecord::Base

# the context available to ALL models

cattr\_accessor :context

# the with\_context method

class \<\< self  
def with\_context(context)  
.synchronize do  
@@context= context  
yield  
end  
end  
end  
end

So we need a mutex.

require ‘thread’

class ActiveRecord::Base  
cattr\_accessor :context  
class \<\< self  
def context\_mutex  
unless defined? @@context\_mutex  
@@context\_mutex = Mutex.new  
end  
@@context\_mutex  
end  
def with\_context(context)  
context\_mutex.synchronize do  
@@context= context  
yield  
end  
end  
end  
end

# WRAP IT ALL UP

If I wrap all this up, I have the lib/context\_system.rb :

require ‘thread’

class ActiveRecord::Base  
cattr\_accessor :context  
class \<\< self  
def context\_mutex  
unless defined? @@context\_mutex  
@@context\_mutex = Mutex.new  
end  
@@context\_mutex  
end  
def with\_context(context)  
context\_mutex.synchronize do  
@@context= context  
yield  
end  
end  
end  
end

module ContextSystem  
def with\_context(context)  
ActiveRecord::Base.with\_context(context) do  
yield  
end  
end  
def with\_session  
with\_context(@session) do yield end  
end  
end

Now, in controllers/application.rb :

require\_dependency “context\_system”

class ApplicationController \< ActionController::Base  
include ContextSystem  
end

I’m now able to write code like I used at the beginning of this post.  
And it works as expected.

# FINAL WORD

What do you think ?  
Of course all this synchronization stuff can’t be seen a perfectly clean  
way of achieving our goal.  
But ?  
Hu ?  
:o)

---

<div class="post-metadata">

**Author:** ![kris](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/82dd89/32.png) [@kris](https://www.ruby-forum.com/u/kris)\
**Post date:** [April 8, 2006, 12:19pm UTC](https://www.ruby-forum.com/t/models-accessing-the-session/93513/15 "2006-04-08T12:19:25Z")

</div>

lagroue wrote:

> Vincent AE Scott wrote:
> 
> > Have a read through: (or should that be :through ?)  
> > [http://www.koziarski.net/archives/2005/07/16/environment](http://www.koziarski.net/archives/2005/07/16/environment)
> > 
> > I think that might be of some use to you.
> 
> Well, no : he uses a class attribute, which is not :secure when requests  
> are concurrent.

Within a given process (which might be WEBrick, or Mongrel, or a FastCGI  
process, or an SCGI process) Rails only handles one request at a time.  
So the approach Koz explains on that page is safe.

regards

Justin

---

<div class="post-metadata">

**Author:** ![kris](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/82dd89/32.png) [@kris](https://www.ruby-forum.com/u/kris)\
**Post date:** [April 8, 2006, 12:28pm UTC](https://www.ruby-forum.com/t/models-accessing-the-session/93513/16 "2006-04-08T12:28:46Z")

</div>

Justin F. wrote:

> Within a given process (which might be WEBrick, or Mongrel, or a FastCGI  
> process, or an SCGI process) Rails only handles one request at a time.  
> So the approach Koz explains on that page is safe.

Not that I doubt what you say, Justin, but : how do you know that ? I’m  
starving for reference documents/web pages on this subject.

Thanks by advance :o)

---

<div class="post-metadata">

**Author:** ![kris](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/82dd89/32.png) [@kris](https://www.ruby-forum.com/u/kris)\
**Post date:** [April 8, 2006, 1:11pm UTC](https://www.ruby-forum.com/t/models-accessing-the-session/93513/17 "2006-04-08T13:11:22Z")

</div>

lagroue wrote:

> Justin F. wrote:
> 
> > Within a given process (which might be WEBrick, or Mongrel, or a FastCGI  
> > process, or an SCGI process) Rails only handles one request at a time.  
> > So the approach Koz explains on that page is safe.
> 
> Not that I doubt what you say, Justin, but : how do you know that ? I’m  
> starving for reference documents/web pages on this subject.
> 
> Thanks by advance :o)

Good question! I know this because I’ve been reading the list for a  
year, taking a particular interest in discussions of Rails architecture.

In the “Selecting a Production Platform” section of “Agile Web  
Development with Rails” there’s the following text:

WEBrick takes the servlet approach. It has a single long-running process that handles each concurrent request in a thread. As weâ??ve discussed, WEBrick is a great way of getting up and running quickly but not a particularly attractive approach for heavy-duty use. One of the reasons is the lack of thread-safety in Action Pack, which forces WEBrick to place a mutex at the gate of dynamic requests and let only one request through at the time. While the mutex slows things down, the use of a single process makes other things easier. For example, WEBrick servlets are the only runtime that make it safe to use the memory-based stores for sessions and caches.

FastCGI and SCGI use a pool of processes, each of which handles one  
request at a time.

However, it’s never been clear to me _what_ is not thread-safe in Rails.

regards

Justin

---

<div class="post-metadata">

**Author:** ![kris](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/82dd89/32.png) [@kris](https://www.ruby-forum.com/u/kris)\
**Post date:** [April 8, 2006, 1:49pm UTC](https://www.ruby-forum.com/t/models-accessing-the-session/93513/18 "2006-04-08T13:49:02Z")

</div>

Justin F. wrote:

> lagroue wrote:
> 
> > Not that I doubt what you say, Justin, but : how do you know that ? I’m  
> > starving for reference documents/web pages on this subject.
> 
> Good question! I know this because I’ve been reading the list for a  
> year, taking a particular interest in discussions of Rails architecture.

:'-/ I’ve been in the party for a week only… :o)

> In the “Selecting a Production Platform” section of “Agile Web  
> Development with Rails” there’s the following text:
> 
> [...]
> 
> FastCGI and SCGI use a pool of processes, each of which handles one  
> request at a time.
> 
> However, it’s never been clear to me _what_ is not thread-safe in Rails.

Thank you _very very_ much, Justin.

Regarding the subject on the thread, I’ll stuck on  
[http://www.koziarski.net/archives/2005/07/16/environment](http://www.koziarski.net/archives/2005/07/16/environment) approach, so,  
and stop fearing concurrency bugs.

Really, thanks.

I’m discovering the Ruby/Rails programs/people/web sites, and still have  
to dig my way into all this new stuff !

---

<div class="post-metadata">

**Author:** ![kris](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/82dd89/32.png) [@kris](https://www.ruby-forum.com/u/kris)\
**Post date:** [April 8, 2006, 1:57pm UTC](https://www.ruby-forum.com/t/models-accessing-the-session/93513/19 "2006-04-08T13:57:54Z")

</div>

lagroue wrote:

> Gazoduc, your secure method gives the session to your Documents, but not  
> to their members. Like, say, this\_document.writer which _is_ a model,  
> and which should be “secured”, too. The “secure” fonction fails doing  
> that.

This was solved by implementing a secure method in the base class of my  
model and doing all the “children” stuff by hand.

I then have some code in validate\_on\_update and validate\_on\_create  
making sure my object has passed through “secure” before it goes into  
the DB, so if I forget to overwrite some Rails clever stuff for  
retrieving data, it breaks on save and my model stays “secured”.

Besides checking for user read/write/publish access, I also use this  
“secure” pipeline to manage multiple languages, passing the desired one  
with user id and groups.

If Webrick and Co are only serving one request per thread, then the  
easiest piece of code for all this is:

$session = session

Isn’t it ?

---

<div class="post-metadata">

**Author:** ![kris](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/82dd89/32.png) [@kris](https://www.ruby-forum.com/u/kris)\
**Post date:** [April 8, 2006, 12:19pm UTC](https://www.ruby-forum.com/t/models-accessing-the-session/93513/20 "2006-04-08T12:19:08Z")

</div>

Xavier N. wrote:

> On Apr 8, 2006, at 10:17, lagroue wrote:
> 
> > I won’t enter in discussion on MVC, because I _do_ need giving session  
> > to models : I want them to be able to store a  
> > creation/modification/destroy event in the database, holding _who_ did  
> > that to them.
> 
> The updates of relationships are done by AR itself, so looks like you  
> need some global magic that sets the user\_id transparently.
> 
> I mean, Document.save(user) won’t work because the (has\_many) Authors  
> children won’t be passed the user by AR. Without more details, it  
> does not sound DRY to manually set the user throughout all the models.

You’re perfectly right, that’s why I chose the with\_session global  
system I described above.

> I don’t know whether this may be helpful, but as starting point you  
> could have a look at acts\_as\_paranoid and see how it modifies AR to  
> deal with a special column in a really transparent way.

I had great hope. But acts\_as\_paranoid alter models by giving them a  
timestamp, and certainly not some data from the controllers.

I’m close to be quite sure the whole AR stuff (and especially  
associations) has to be updated if we want a controller to spread a  
context in the models it uses.

And this would not be the actual solution : imagine that a controllers  
updates the @session[:user] model. This object has been created _before_  
the controller was awake. Thus the controller did not give its session  
to that user. And we’re doomed again.

[Next page](https://www.ruby-forum.com/t/models-accessing-the-session/93513.md?page=2)
