For fuck’s sake, STOP asking this question in IRC
You’re completely/totally/fucking wrong if you want to access sessions, params, cookies, etc. in your Models.
You can’t get more wrong than this in rails world probably. But some people just don’t get it. So if you must, this is how you can do it ( I’d suggest you go back to PHP or whatever ) :
Add this code at the bottom of your application.rb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
class ApplicationController < ActionController::Base # Your existing stuff around_filter :you_dont_have_bloody_clue protected def you_dont_have_bloody_clue klasses = [ActiveRecord::Base, ActiveRecord::Base.class] methods = ["session", "cookies", "params", "request"] methods.each do |shenanigan| oops = instance_variable_get(:"@_#{shenanigan}") klasses.each do |klass| klass.send(:define_method, shenanigan, proc { oops }) end end yield methods.each do |shenanigan| klasses.each do |klass| klass.send :remove_method, shenanigan end end end end |
Again, do it if you wish, just don’t ask anyone how to do it ever again!





Yr code shenanigans always make me laugh.
“methods.each do |shenanigan| ” nearly made me cry. That’s frickin’ awesome.
Haha :) Good job Pratik, you’re teaching them crap :P
For your next article I propose: ‘How to query the database directly within .erb’
Or you could do something like this:
http://scie.nti.st/2007/2/1/let-activerecord-observers-see-controller-context
Since the behavior of an observer may depend in which context it was invoked, I’ve used code like that on a couple of occasions.
LOL thank u ive been looking 4 this 4 ages…... do you know y doesnt this works? Can u help me???
<%= link_to_remote ‘Read article’, :controller => ‘articles’, :class => ‘ajax’, :action => ‘get_article_js’, :onclick => ‘return false’, :update => $(‘article_#{article.id}’).innerHTML %>
Im making an AJAX desktop!!
class Book < ActiveRecord::Base def self.my_books # use Goldberg.user to have access to current_user object which was copied from session and saved as a class attributed end endI literally pulled my hair out and asked myself why?I enjoy cache sweepers. Look at this:
class AuthorStampSweeper < ActionController::Caching::Sweeper observe Task, Project, User, Log, UrMom def before_create(record) record.creator = current_user end def before_update(record) record.updater = current_user end endYay! And you have to call it from the controller, so everything makes a lot of sense. I prefer this method instead of passing the user id to some accessor in the model or something.
@ August Lilleaas. Except that passing the user’s id to the model is the right [and elegant] way to do this.
i don’t don’t see anything wrong with accessing the sessionid in a model to help prevent against csrf attacks.
cheers, tom
HeresTomWithTheWeather – U-hum..could you please shed some more light on that ?
suppose we add a hidden :action_token field in a form_for. the value of the field is derived from the session id (for simplicity, let’s assume it’s just the session id), so let’s add attr_accessor :action_token to the model.
how will we set the session id to the action token field for new and edit? we could do it in the controller for new():
@request = Request.new @request.action_token = session.session_id
and again for edit():
@request = Request.find(params[:Id]) @request.action_token = session.session_id
and when we process the submitted action token, we could do this in create():
@request = Request.new(params[:request]) process_forgery() if @request.action_token != session.session_id
and again for update():
@request = Request.find(params[:id]) process_forgery() if @request.action_token != session.session_id
or we could just explicitly add methods to the model so we don’t have to add all this stuff to the controller.
in theory, we could use Garry’s observer idea. i had trouble getting after_initialize() to work with STI, though.
-tom
Probably you should check out Rails built in CSRF protection mechanism.
now that 2.0 is out, i can!
http://weblog.rubyonrails.org/2007/12/7/rails-2-0-it-s-done
thanks, tom
Ok i can see how breaking MVC is bad. But how would you solve the issue of recording modified_by and created_by where most tables have those columns and you are looking for a auto pain free way of taking the current_user and putting there id or login into those fields???? That is a very real problem and i don’t feel like having Model.modified_by = current_user all over the place be rather prefer it to work like updated_at and created_at
How about the simple task of Auditing changes? On a website where Users make changes to all kinds of objects I want to store the changes in a SystemLogs table.
A model with no reference to a User object whatsoever (or atleast not directly) gets changed by a user. Now whenever Model.save is called in the controller I want to create a SysLog record/instance with the changes and the user_id of the calling user.
To do this from the controller violates the DRY principle, as every .save / .update call from different controllers need to be followed by a specific creation of a SysLog object.
in my specific case auditing causes the DRY principle to conflict with the MVC model
I have examples where models writing to a session is the only thing that makes any real sense from an API and DRY standpoint as well. IMO, a session is not solely the domain of the controller. It is a system wide bucket for storing state during a visit. It should be available to the entire framework. Can it be abused? Sure, so can every tenet of programming. Considering the wide opinions on just about every facet of OOP details, it cannot be claimed to be absolutely wrong for both controllers and models to make use of a session store.
Because Rails doesn’t allow it, there’s some ugly APIs that result for those cases where automated handling of tasks by the framework or a service layer just on top of it are handled. the two examples above are legit IMO, and I have at least one other.
class ApplicationController < ActionController::Base before_filter :set_current_user private def set_current_user UserActionObserver.current_user = current_user end end class UserActionObserver < ActiveRecord::Observer # assuming these all have created_by_id and updated_by_id observe Product, Thing, OtherThing cattr_accessor :current_user def before_create(model) model.created_by = @@current_user end def before_update(model) model.updated_by = @@current_user end endPratik, you are being a royal cock about this.
Surely, adding your own custom logging to a rails app, WITHOUT having to go mess with the controller methods that call save on your model in order to pass the username stored in the session to the model by just making the session data available to the model is WAAAAY more DRY and elegant than going back and fucking around with controller methods.
You dumbass.
I don’t understand the appeal of the observer examples. What is wrong with going through the current_user’s association proxies to build and create new records in the controller? It makes the code too clear? The logic isn’t split up into enough files and classes with implicit behavior?