views:

303

answers:

2

I would like to show each user who has visited her/his user profile. At first it looked easy as the acts-as-readable plugin does everything I need. However this plugin does not work from the user model.

What if in the future I decided to add visitors to articles, albums etc.

/usr/local/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/base.rb:1833:in `method_missing': undefined local variable or method `acts_as_readable' for #<Class:0xb70d1bfc> (NameError)
        from /home/www/ror/app/models/user.rb:22
        from /usr/local/lib/ruby/gems/1.8/gems/activesupport-2.2.2/lib/active_support/dependencies.rb:382:in `load_without_new_constant_marking'
        from /usr/local/lib/ruby/gems/1.8/gems/activesupport-2.2.2/lib/active_support/dependencies.rb:382:in `load_file'
        from /usr/local/lib/ruby/gems/1.8/gems/activesupport-2.2.2/lib/active_support/dependencies.rb:521:in `new_constants_in'
        from /usr/local/lib/ruby/gems/1.8/gems/activesupport-2.2.2/lib/active_support/dependencies.rb:381:in `load_file'
        from /usr/local/lib/ruby/gems/1.8/gems/activesupport-2.2.2/lib/active_support/dependencies.rb:256:in `require_or_load'
        from /usr/local/lib/ruby/gems/1.8/gems/activesupport-2.2.2/lib/active_support/dependencies.rb:427:in `load_missing_constant'
        from /usr/local/lib/ruby/gems/1.8/gems/activesupport-2.2.2/lib/active_support/dependencies.rb:77:in `const_missing'
         ... 31 levels...
        from /usr/local/lib/ruby/gems/1.8/gems/mongrel-1.1.5/bin/../lib/mongrel/command.rb:212:in `run'
        from /usr/local/lib/ruby/gems/1.8/gems/mongrel-1.1.5/bin/mongrel_rails:281
        from /usr/local/bin/mongrel_rails:19:in `load'
        from /usr/local/bin/mongrel_rails:19

Does anyone know a alternativ plugin that can do this? (user1.users_who_read etc) It is a shame that act-as-readable don't work in the user model. It had been really useful to just drop in this functionality to selected models.

Best regards. Asbjørn Morell.

+1  A: 

Why not roll your own?

class User < ActiveRecord::Base
  has_many :user_visits
  has_many :visitors, :through => :user_visits, :source => :visitor
end

class UserVisit < ActiveRecord::Base
  # user_id :integer
  # visitor_id :integer
  # visited_at :datetime

  belongs_to :user
  belongs_to :visitor, :foreign_key => 'visitor_id', :class_name => 'User'
end


User.first.visitors = [user_1, user2]

You could use STI in you're going to have that many *vists join tables. YMMV as it complicates things such as caching. I'd rather having a little "wetness" on the code side if it makes for a faster experience.

Matt Darby
Alright. I will skip STI for as it might get to complicated. I was just wondering why the "has_many :visitors, :through => :user_visits" is nessary? Would User.user_visits not return the same result?
atmorell
User.user_visits will return a UserVisit object, not a User object that actually visited the User's page.You don't *need* it, but it's much cleaner with it; otherwise you'd have to do: @user.user_vists.first.user instead of @user.visitors.first
Matt Darby
A: 

Hmmm this is really giving me some problems:

User.first.visitors
ActiveRecord::HasManyThroughSourceAssociationNotFoundError: 
Could not find the source association(s) :visitor or :visitors in model UserVisit.  
Try 'has_many :visitors, :through => :user_visits, :source => <name>'.  
Is it one of :user?

I tried to add :source => :user to my user model. However then I only get the owner when doing user.visitors.

This is my migration:

class CreateUserVisits < ActiveRecord::Migration
    def self.up
     create_table :user_visits do |t|
      t.integer :user_id
      t.integer :visit_id
     end
    end

    def self.down
    drop_table :user_visits
    end
end

Any thoughts?

atmorell
If you want information about the visit, then you'll need to work with @user.user_vists. @user.visitors will only return Users that visited the original User.
Matt Darby
Matt, Active Record gives me the error above without :source => :user added to has_many :visitors,.... When I do user1.visitors each visit record is just the owner and not the visitor itself. user1.visitors => [user1, user1, user1]
atmorell
Look at my original answer, I updated it to correct an association.
Matt Darby
Much better :) I was wondering how you would create a new user_visit? I would just do @user.user_visits.build(:visitor_id => current_user.id).save but maybe there is a cleaner way? Should I delete my last answer as all problems has been sorted out in your first answer?
atmorell
I added a few methods to my user model: http://github.com/mbleigh/acts-as-readable/blob/37cd25589fd85fc643ffacd32b131e52f549bb60/lib/acts_as_readable.rb Now I can do user1.visited_by!(user2) etc
atmorell