Newbie trying to teach himself relationships (dangerous)

Hi Guys,

I am trying to learn ruby on rails as well as computer programming in
general. I am a little confused about relationships.

I want to create a 'has and belongs to many' relationship by making my
books taggable. I don't know what the difference between a tag vs
category.

I want to add categories to my book application and have them
displayed just like you see on blogs but I don't get it. Be nice
please, I am very new.

Whenever somebody creates a new book object I want them to be able to
assign the book to a category and display it, if a category doesn't
exist yet, I want the book object to create it. I also want books to
be able to perform CRUD operations and be able to add/remove/etc..
books from categories.

I am really lost on how to do it. I am starting to understand the ruby
syntax well enough, but I don't get the logic.

Can someone please give me an example on how I do this and explain it
to me like I'm a total newbie?
Or in the least, provide me with links explaining how you would do
this.

Thank you very much for your time and helping.

Nevyn

Hi Guys,

I am trying to learn ruby on rails as well as computer programming in
general. I am a little confused about relationships.

I want to create a 'has and belongs to many' relationship by making my
books taggable. I don't know what the difference between a tag vs
category.

....

Can someone please give me an example on how I do this and explain it
to me like I'm a total newbie?
Or in the least, provide me with links explaining how you would do
this.

This may help:

http://mboffin.com/stuff/ruby-on-rails-data-relationships.png

First of all, welcome to Rails and to programming. You have no
apologies to make, all of us had to start somewhere, and getting
advice from this community is a great way to start.

As to your question about book categories/tags: There are multiple
ways that you can implement categories in an application, depending on
your problem domain.

The simplest is a one-to-many relationship. In this case a Category
would contain many Books, but an individual Book would be listed under
a single Category. If that scenario works for you then go with that.
It's makes the implementation quite a bit easier.

If you need to allow an individual Book to be listed under multiple
categories, then you would need to model a many-to-many relationship.
There are two ways to accomplish this, again depending on your use
case. You could associate them using a has-and-belongs-to-many (HABTM)
as long as you have no need to expose additional attributes within the
join table used to categorize books. Using this type of relationship
has some disadvantaged if you are planning to use a RESTful controller
style. What I mean by this is that you would need custom actions on
the categories or books controllers (or both) in order to maintain the
relationship. The other option is to use a has_many :through
relationship where the join table would be exposed as a resource with
its own CRUD operations that can be used to maintain the relationship.
Maybe you could call that joining resource something like
Categorization. When you want to associate a Book to a Category you
would use a "create" action to do that. To disassociate them you would
use a "destroy" action.

Another design pattern I've used in the past had the concept of
subcategories, where the Category object was represented by a "tree
structure." In the Rails world this could be handled by using the
acts_as_tree plugin. This would incorporate a "reflexive"
relationship. That's just a fancy way to sat that it is a relationship
that wraps back to the same table. These types of relationships can be
either one-to-many or many-to-many. In the former case the tree is
represented by a single table containing a foreign key back to a
different row in the same table. In the latter case there would be two
tables where the second acts as a join between two different rows of
the first table. Note: this is a fairly advanced technique, but I just
wanted you to be aware of it.

About your question of categories vs. tags. I would not consider the
type of categories here as tags. These are two separate concepts.
Categories are sort of "hard linked" relationships for organizing
books within your store. Tags are generally more free form and
something intended for the user's domain. At least from the "social
networking" point of view. There are some nice plugins available to
help you with tagging resources. Look for acts_as_taggable for more
details.

Robert, thank you very much for taking the team to help me! It's nice
to see that there are kind people on this list!

I decided to use the one-to-many approach.

Book belongs_to :category
Category has_many :books

This seems to be okay, I have been playing around in irb and really
confusing myself yet again, so maybe you can help. I'm sure this is a
simple problem for most, but I just have not' been able to UNDERSTAND
yet. I am close though..

I now have my relationship in place, but what if I want to find all
the book by a certain category.
I'm confused on how that works. I am reading up on it, but I don't
understand it.

Would I put a method in my BookController that finds all categories?
But how do I display the book in a view.

To make it simple,

I want to find all books by category name. Do I need to create a new
route for this?

I want the URL to be like http://foo.com/categories/book_name and then
list all the books that are in that category.

I keep getting nil objects and no method errors when I try. I am now
grasping at straws since I seem to have confused myself terribly.

Thanks again.

You can put your method in any controller you like. In this case lets
say Book controller. The method is going to be like this:

def find_books_for_category
  all_books = Book.find_all_by_category_id(params[:id])
  # another way would be :
  all_books = Category.find(params[:id]).books
end

For the url you can define it in you routes.rb file within config
folder like
map.connect 'categories/:id', :controller => 'book', :action =>
'find_books_for_category'

but the url you will get will be some thing like http://foo.com/categories/5
however you can get something like http://foo.com/categories/5-book_name

if you will add this in your book model
def to_param
    "#{id}-#{book_name}"
end

I don't think its a good idea to use a url like http://foo.com/categories/book_name
because multiple books can have the same name which will give you
unpredicted results.

I don't think its a good idea to use a url like http://foo.com/categories/book_name
because multiple books can have the same name which will give you
unpredicted results.

Well, this is just an app for me to learn rails. I can do it by
params[:id] but I am more curious to know how to find all books by
category name, more for my own knowledge than practical design. I've
tried but I still can't figure it out.

thanks so much for everything this far, you guys have been very helpful!

then considering you have an attribute called category_name in your
Category model, you can do it like this

all_books =
Category.find_by_category_name(params[:category_name]).books