Applying what I've learned...

Subscribe to Applying what I've learned... 19 post(s), 3 voice(s)

 
Avatar Roupen 84 post(s)

Eldon, I’m trying to apply what I’ve learned so far (from the Monkey and Exerciser chapter) into a hobby application that might be potentially useful to college students. The idea is that users would list textbooks that they have and textbooks that they need and the app would match them up. The difference, so far, between a wanted book vs. an offered one is “condition” of the book.

How would you lay the groundwork for something like this?

I’ve defined a Book model and a controller called Admin that handles listing, adding and deleting items to a list. I’ve been also toying with the idea of having two models: wantedbooks and offeredbooks with matching controllers to manipulate the models with. The view so far is simple—the page has two halves offered/want with an “add” button for each section. Each add action can call the appropriate controller, etc. But I’m worried about doing unholy things OO-wise :) I’m also seeing that I may be going down a path that is going to lead a lot of code duplication :(

 
Avatar EldonAlameda Administrator 216 post(s)

I’d probably need to think about it and sketch it out for a day or two to get a good feeling for it—but my initial thought is that it might make sense to do something like this:

So you’d have
  • A User model for each student
  • A Book model for each book
  • An Owns model which contains foreign keys to users and books to list which users owns which books (in a has_many :through association)
  • A Needs model which contains foreign keys to users and books to list which users are looking for a book (in a has_many :through association)

So you could go from a user to any book that they want. From that book you could go back to a list of users that have the book available for. By making those associations model you can add additional information in there as well such as quality of book, number available, price willing to pay, etc

Thats just off the top of my head after a few minutes of thought – so it might have a snag or two. But hopefully it helps.

 
Avatar Roupen 84 post(s)

Yes, this makes sense and it validates the path (of 3 models) that I was going down…

How do “Needs” and “Owns” mesh with Ruby naming conventions? A “book” model becomes “books”. Would “Needs” and “Owns” confuse things?

Re: Book, Needs, Owns – can a single controller manage them all or do you see a need to have separate controllers for each?

 
Avatar EldonAlameda Administrator 216 post(s)

you can always override the table name for a model with the set_table_name method, or you could change the name of the models. The key is to look for something that makes sense and presents itself as readable as possible. What we’re doing here is trying to model the relationships between a book and a user.

As for a single controller – it all boils down to a question of how close you want to keep your controllers to the CRUD ideal. There’s nothing that says that you have to create a separate controller for each model. I probably would create a controller for each of those models but that’s just me.

 
Avatar Roupen 84 post(s)

OK – quick Q :) how do you add an image into a post?

 
Avatar Roupen 84 post(s)

I read-up on habtm – rich topic… I wrestled with the Owns/Needs names prob more than I should have… going down set_table_name route felt like a punt…

I’m not sure if the multiple “through” statement below is correct but… trying to create the “square” path in the diagram (can get to from books to users via wanted_offers and have_offers). What do you think?

Class User < ActiveRecord::Base
  has_many wanted_offers
  has_many have_offers
  has_many books :through => wanted_offers, :have_offers
end

Class Book < ActiveRecord::Base
  has_many wanted_offers
  has_many have_offers
  has_many users :through => wanted_offers, :have_offers
end

Class HaveOffer < ActiveRecord::Base
  belongs_to :book
  belongs_to :user
end

Class WantedOffer < ActiveRecord::Base
  belongs_to :book
  belongs_to :user
end

Is a :dependent call needed here? since a wanted_offer or a have_offer won’t exist without a valid book…

 
Avatar EldonAlameda Administrator 216 post(s)

Trying to give you hints / nudges without just solving it for you :-)

In the diagram i was more talking about it from an association point of view. Remember the goal is to model the relationship between a book and a user. So to me one way of modeling that relationship might as “ownership”. So if you were to follow that idea – an ownership model might also have a quantity field. If I user wants a book i would set that quantity to a negative number. If a user has a book but is not willing to trade it at this point then the quantity would be zero. If the user has the book and wants to trade it – then that value would be set to a positive number. Doing it this way you could also support if someone was looking to either obtain or trade multiple copies of the same book. I.e. looking to get 12 copies of a book would create an ownership record with a -12 value in the quantity.

So from here you would just need to create your has_many :through associations correctly and pass in the appropriate conditions (i.e. quantity > 1) to each association.

 
Avatar Roupen 84 post(s)

A nudge is always appreciated :) Let me digest the ownership and give it a try

Meanwhile, I went down the road and implemented the original 4-model approach… I’m able to create a “Wanted” book, list and delete. And I’m currently wrestling with the Show and Edit. I’m a bit stuck (trying to traverse child models back to the parent, etc. which tells me that the 4-model approach my be over complicating it) :)

 
Avatar Roupen 84 post(s)

PS: Can I attach a diagram to a post as u had?

 
Avatar Roupen 84 post(s)

OK i think i get the “ownership” approach—see representation below.

Here is the matching algorithm I am thinking of … it seems like want/have should be tracked separately (as objects?). Nudge me :)

  1. Find all users with >= 1 want and >=1 have book listed; this is the match pool.
  2. Go through the want list for each user in the match pool. Take the first want-item X for user A and find all users in the match pool with a have-item X; this is the partial match list for user A item X.
  3. For user A take have-item Y and find all users in the partial match list with want-item Y; this is the match list for user A and item X. Repeat for everyone in the match pool.
Class User < ActiveRecord::Base
  has_many :ownerships
  has_many :books :through => :ownerships
end

Class Book < ActiveRecord::Base
  has_many :ownerships
  has_many :users :through => :ownerships
end

Class Ownership < ActiveRecord::Base
  belongs_to :user
  belongs_to :book
end
 
Avatar EldonAlameda Administrator 216 post(s)

OK – quick Q :) how do you add an image into a post?

Textile just has you put exclamation marks before and after the url to the image

 
Avatar EldonAlameda Administrator 216 post(s)

Heres one last nudge… :-)

class Ownership < ActiveRecord::Base
  belongs_to :user
  belongs_to :book
end

class Book < ActiveRecord::Base
  has_many :ownerships
  has_many :needs, :through => :ownerships, :source => :user, :conditions => 'quantity < 0'
  has_many :owns,  :through => :ownerships, :source => :user, :conditions => 'quantity > 0'
end

class User < ActiveRecord::Base
  has_many :ownerships
  has_many :needs, :through => :ownerships, :source => :book, :conditions => 'quantity < 0'
  has_many :owns,  :through => :ownerships, :source => :book, :conditions => 'quantity > 0'
end

Now those models aren’t complete so you’ve still got a little work to do on your own (one more hint – think about making sure that there is only one row in the ownership table for a given book and user).

But once you get this going you’ll be able to simply calls owns and needs on a user object to collect a list of book that that user has or is looking for.

Just build it out and play around with it in script/console—adding users / books and ownerships and modifying the models as needed until you get it. Playing around with it is the best way to learn.

 
Avatar EldonAlameda Administrator 216 post(s)

Couple of good resources for learning more about how to use has_many :through

Railscast Screencast

Josh Susser has blogged about them numerous times over the years at his blog

I can’t remember 100%, but I think they were covered in RailsEnvy’s screencast on ActiveRecord

 
Avatar Roupen 84 post(s)

Much to digest - much appreciated Eldon :)

 
Avatar Roupen 84 post(s)

Quick update – i just went through the sources you posted – a wealth of good stuff.

I’m letting the stuff settle into my gray matter before I take a dive and build out what you started… I hope to make you proud Sensei :)

 
Avatar Roupen 84 post(s)

I’ve been going through these screencasts and they are incredibly useful (the relaxed style of the authors is very calming). I’m wondering if Eldon or others have come across other railcasts that you’d like to share.

PS: I’m getting back to the project in this thread (got hit by the flu for a couple of days).

 
Avatar Neil 9 post(s)

Yeh, Railscasts rock. Ryan Bates does an awesome job of explaining everything. You feel like just you’ve just spent a day at relaxation-health-spa after each screencast!

 
Avatar EldonAlameda Administrator 216 post(s)

I hate to admit it but i stay up until 2am every sunday night just so I can check out the newest RailsCast.

But I’m also a night-owl and more than a bit obsessive. Some of my first pure ruby scripts (i.e non-rails) were scripts that would load a page on the some book publishers websites and immediately notify me if a book I was waiting for was available for purchase now (that site didn’t have an RSS feed back then).

For other screencast goodness – there’s also Peepcode.com which I’m sure you’ve seen reference to from the RailsCasts.

Rubyplus.org is a new site that recently started Ruby and Rails screencasts, I’ve only downloaded two of those so far but the audio had issues to where it was a real pain to make out what he was saying so I haven’t been back. Maybe they’re fixed now.

 
Avatar Neil 9 post(s)

Rails Envy podcasts are also worth checking out. I have smile on my face the whole time I’m listening to them, which is usually while I’m stumbling round for a bowl-cereal-milk combination.