Topic: Accessing Session Data from Model

I have looked everywhere and even chatted on IRC, but no one seems to have an answer for this. It seems so simple too.

All I want is to be able to track which user updated or created an article. I already have created_by and updated_by fields in my table, and thenI attempt to hook the session user id through a before_save callback. I quickly discovered that session data is only accessible to the controller and have attempted several methods to overcome this...none of them have worked.

Any pointers would be a godsend

Re: Accessing Session Data from Model

In the controller:

@article.created_by  = session[:user_id]
@article.updated_by = session[:user_id]

Re: Accessing Session Data from Model

That didn't do the trick either, since instance variable containing session data are not accessible to either models or observers.

Fortunately, I just got my copy of Rails Recipes and there is one for this particular problem, using a separate audit model with cache sweepers. Will let you know how it goes.

Re: Accessing Session Data from Model

In my example, you'd save the user.id to the article.created_by to be saved by the model. Then, if you need access to see who created what articles, you can write a special find in your model such as:

def find_all_by_john
  find_all_by_name("john")
end

There is no reason why you should be trying to manipulate session data within your model. You would be confusing the MVC architecture.

If all you really want to do is track who created/updated what, you'd just dump the user.id into the created/updated by columns via the controller to be saved by the model. If you need to access the user.id on a before_save filter then you can access the id via the created/updated by value.

Re: Accessing Session Data from Model

Do you think iit would be better architecture to have a table/model to track this sort of activity? It would certainly cut down on repetitive columns across my models (About 9 of them)

Re: Accessing Session Data from Model

Have you thought about a before filter in your controller?

Perhaps if you explain a bit more, with some code, I can understand a bit more of what you are exactly trying to accomplish, because it seems we are talking past each other.

Re: Accessing Session Data from Model

In a nutshell I want to be able to look at certain model instances and see "Created on 4/12/07 by Some User"  and  "Updated on 4/12/07 by Some User"

As it stands, I have set up a few of my models with updated_by and created_by columns. I was obsessed with trying to populate these fields with a callback,

def before_save
  self.updated_by = current_user.login
end

but now I am wondering if this is the smartest approach. Before I try and go the route I originally proposed, do you think it would be wiser for me to have some sort of external model, perhaps named Activity, that could somehow use joins to monitor user creation and modification of instances?

I only wonder this as I am at the point of putting updated_by and modified_by columns in all my tables, but somehow that doesnt feel DRY to me.  What strategy would you use?

Re: Accessing Session Data from Model

OK, I understand that you have at least 1 table that records the created_by and updated_by. Insisting that that current_user or User.current_user should be in the model is not the MVC way and is frowned upon by the Rails community.

There is no need for an external model to do something that your controller ought to be doing. There are several things that you can do, one being what I said above. Another that would by DRY'r would be do:

@article = current_user.articles.build params[:article]
if @article.save
  flash[:notice] = "Yeah, I am saved with my id"
  redirect_to_some_action
else
  render :action => :new
end

Re: Accessing Session Data from Model

Looking at your example I thought to myself: "I've never seen a 'build' method before."

Apparently I'm not alone...

undefined method `build' for #<User:0x33002fc>

Re: Accessing Session Data from Model

1) Double check your code, the error looks like it was written wrong.
2) Check your Model Associations (has_many, belongs_to)
3) Look at the API (http://caboo.se/doc/classes/ActiveRecor … ml#M005504)
4) Go to The Rails Way and look at the first article. (http://www.therailsway.com/)

Re: Accessing Session Data from Model

1) I copied the code exactly as you posted (minus the generic stuff which I have customized)
2) I think has_many doesn't apply here. It's really more of a many-to-many thing because multiple authors can edit one article.
3) According to the API it looks like the build method takes an argument of alocal variable set to a hash. In your example it looks very different.
4) Same issue as #2. I dont want to assign ownership to articles, just track who does what.

Thanks for the pointers and links though. Its already been educational smile

Re: Accessing Session Data from Model

1. If you had your models as has_many belongs_to, then there is most likely an error in the code you posted.
2. This is one of those things I call "coding blind" as you didn't share much of your model setup.
3. If you actually try using has_many/belongs_to and test out the code, you will find that it works quite well.
4. Assigning a user_id does not necessarily assign ownership unless you set up the rest of the system to work in that way. Just assigning a user_id does nothing more than give it an id.

The API is a developers best friend and when you ask for help it is usually considered good manners to not be rude to someone who is helping you:

Ace of Dubs wrote:

Looking at your example I thought to myself: "I've never seen a 'build' method before."

Apparently I'm not alone...

Re: Accessing Session Data from Model

My bad Robert,

I certainly didn't mean to be rude. You are a big help to Rails folk here... certainly one of the reasons I even considered using it to begin with.

I'm off on a road trip this weekend and will try out your suggestion when I get back. In the future I will definitely make the effort to give clearer illustrations of my code and desired functionality.

As for the API, I really do need to use it more. The problem is that (dont laugh) I find it ugly to look at. The code examples are not even colored for clarity and the layout could be more intuitive. Also the explanations of classes and methods are pretty terse if you are not a hardcore programmer. Of course, only a designer would make these complaints.. tongue

Last edited by Ace of Dubs (2007-04-19 00:30:29)

Re: Accessing Session Data from Model

Alrighty, so i tried this out like you said.

- User has_many :articles
- Article belongs_to :user

In my create action I have

@article = current_user.articles.build params[:article]

followed by a RESTful respond_to block

I go and create a record, and there are no errors whatsoever, but the created_by field is blank.

Looking at the code you posted I am wondering if perhaps that build method needs to be aware of the column I am trying to populate?

Re: Accessing Session Data from Model

That's probably because you haven't set your forgein key to created_by. Rails will map your forgein key to user_id (model_id) by default.

Here's a working example that I wrote for you to look at: Using Build with proper Associations

Re: Accessing Session Data from Model

Doh!

Of course you are right as always.

Thanks for taking the time to post this.. but the link you sent me is 404ing

Re: Accessing Session Data from Model

Try it now.

Re: Accessing Session Data from Model

Thanks so much for putting this together.. I finally got my current_user to show up in my created_by field!

The only hurdle left is to figure out how to display the user name instead of the ID. I checked out the API, but it's all ActiveRecord code.. no mention of how to write instance variables for the association.

I tried getting clever with @article.user.login, but that didnt work.

Re: Accessing Session Data from Model

So I figured it out... by using the created_by field as an argument for find_by_id, I am able to fetch the user login.

Amazing how simple and powerful this is. I cannot thank you enough for your help.

smile

Re: Accessing Session Data from Model

Woops..spoke too soon.

Running your demo app, I can populate the created_by field no problem, but i get errors for update

You have a nil object when you didn't expect it!
You might have expected an instance of ActiveRecord::Base.
The error occurred while evaluating nil.update_attributes

It makes sense to me too, if the user is not yet associated with a certain article, then the object current_person.articles should turn up nil.

Im gonna dig into the API a bit and see if there is another method, similar to build that works for updates.

I'm so close I can taste it!

Re: Accessing Session Data from Model

I didn't add anything for the update, left that for you to do.

Re: Accessing Session Data from Model

I figured it out.. all I needed to do was explicitly set the attribute on the update action.

@term.updated_by = current_user.id

Works without so much as a hiccup. And to think, I was going to use a whole different model with cache sweepers and callbacks...pffft what was I thinking?