416serg
416serg

Reputation: 448

Add an array field to a user database in Rails

I have an app that has a search box where you input a Twitter username and it returns the recent mentions of that user. https://hurrier-app.herokuapp.com/

Some tweets have an image associated with them. I need to be able to "favourite" an image and then be able to view all of them on a separate page.

I am very new to Rails so I was thinking of adding an array fav_pics to the user model and appending each photo's url to it upon favouriting it. not sure where to start.

here's my user.rb

class User < ActiveRecord::Base
  def self.from_omniauth(auth)
    user = where(provider: auth.provider, uid: auth.uid).first || create_from_omniauth(auth)
    user.oauth_token = auth["credentials"]["token"]
    user.oauth_secret = auth["credentials"]["secret"]
    user.save!
    user
  end

  def self.create_from_omniauth(auth)
    create! do |user|
      user.provider = auth["provider"]
      user.uid = auth["uid"]
      user.name = auth["info"]["nickname"]
    end
  end

  def twitter
    if provider == "twitter"
      @twitter ||= Twitter::Client.new(oauth_token: oauth_token, oauth_token_secret: oauth_secret)
    end
  end

  has_many :fav_pics
  has_many :pics_favorited,
    class_name: 'Pic',
    through: :fav_pics

end

class FavPic < ActiveRecord::Base
  belongs_to :user
  belongs_to :pic
end

class Pic < ActiveRecord::Base
  has_many :fav_pics
  has_many :fav_users,
    class_name: 'User',
    through: :fav_pics
end

now how do I actually handle the "favourite" event? I have experience with Meteor (javascript) but I am not sure how to handle events in Rails. Any resource links would be much appreciated.

Upvotes: 0

Views: 46

Answers (1)

tadman
tadman

Reputation: 211750

That's the right idea. What you're describing is a join relationship, where to models are related by a third that pairs them.

For example:

class User
  has_many :fav_pics
  has_many :pics_favorited,
    class_name: 'Pic',
    through: :fav_pics
end

class FavPic
  belongs_to :user
  belongs_to :pic
end

class Pic
  has_many :fav_pics
  has_many :fav_users,
    class_name: 'User',
    through: :fav_pics
end

That's generally the key here. Normally the middle table has a compound index on user_id and pic_id with a UNIQUE constraint so people can't favorite twice.

Using array-type columns, especially when they're not natively supported by your database, becomes extremely expensive and difficult to work with. Manipulating them requires re-writing the entire user record, so as people favorite more images the cost of an update increases. Likewise, finding all users that have favourited an image is computationally expensive to reverse.

If you're using an RDBMS, structuring it with conventional tables is usually the best plan.

Upvotes: 4

Related Questions