views:

40

answers:

2

Hello, Rails newbie... trying to understand the right way to do things...

In my app users can create a Book ( I have that working)

What I want to happen is when a user creates a book, a record is added to the BookCharacters Table, something like (id, book.id, user.id, characterdescription.string.)

When the book is created, the user who created it should automatically be added as the first BookCharacter. After than the user can then manually add/edit as many BookCharacters as they want. But initially I want them added automatically by default.

So in my Book controller I have:

def create
 @book = Book.new(params[:book])
 respond_to do |format|
  if @book.save
....

With Rails, is it the practice to add that kind of logic after the book is saved? Something like

Book.create( :creator => current_user.id)

I appreciate the help

A: 

I prefer something like (if User has_many Book):

def create
 @book = current_user.books.new(params[:book])
 respond_to do |format|
  if @book.save
  …
Yannis
Thanks but My question was about creating BookCharacters... Maybe I can edit to clear that up better?
AnApprentice
Yes, my mistake. Great answer by @zetetic!
Yannis
+1  A: 

The important thing to understand is the convention by which Rails implements relationships using ActiveRecord. A book has many characters, and each character belongs to a book, so:

class Book < ActiveRecordBase
  has_many :characters
end

class Character < ActiveRecordBase
  belongs_to :book
end

Rails now assumes that the characters table will have a foreign key called book_id, which relates to the books table. To create a character belonging to a book:

@book = Book.new(:name=>"Book name")
@character = @book.characters.build(:name=>"Character name")

Now when @book is saved (assuming both @book and @character are valid), a row will be created in both the books and the characters tables, with the character row linked through book_id.

To show that a character also belongs to a user, you could add that relationship to the Character model:

class Character < ActiveRecordBase
  belongs_to :book
  belongs_to :user
end

Thus Rails now expects characters to also have foreign key called user_id, which points to a users table (which also needs a User model). To specify the user when creating the character:

@book = Book.new(:name=>"Book name")
@character = @book.characters.build(:name=>"Character name",:user=>current_user)

You can also assign the foreign key by calling the corresponding method on the object:

@character.user = current_user

This all works because it follows the Rails conventions for naming models and tables. You can depart from these conventions, but you'll have a harder time learning Rails if you do.

zetetic
That's the best answer I've ever seen. Thanks for helping me understand the right way to use Rails
AnApprentice