Ok here are my notes on setting up a many to many association including
adding child records to the parent, both directions. Please comment and let
me know what you think. Once the dust settles I'll post it as a recipe on
hobocentral.
Bob
Many to Many in Hobo
Start out with a new hobo app
hobo g resource book title:string
hobo g resource author name:string
hobo g model book_author
Add has_many assotications to book.rb, author.rb and book_author.rb
Add to book.rb
has_many :book_authors, :dependent => :destroy
has_many :authors, :through => :book_authors, :accessible => :true
children :authors
Add to author.rb
has_many :book_authors, :dependent => :destroy
has_many :books, :through => :book_authors, :accessible => :true
children :books
Add to book_author.rb
belongs_to :book
belongs_to :author
create and run the migration
hobo g migration
Run the app
At this point you can add authors to books and books to authors but the book
or author must already exist. There is no direct way to add a new author to
a book or new book to an author you need to first create the book/author and
then make the association separately. Wouldn't it be nice to be able to add
a new author to a book while editing the book? You can do this very easily
with Hobo and auto_actions_for int he control in a one to many association
but that doesn't work totally automaticly for many to many associations.
First we are going to use Hobo's auto_actions_for in the controllers to
create the routes for us.
Add to authors_controller.rb
auto_actions_for :books, [:create, :new]
Add to books_controller.rb
auto_actions_for :authors, [:create, :new]
If you go to a book or author you won't see any changes to the UI. If this
were a one to many association we would have a New link below the collection
of books or authors but there isn't one so lets add it.
First lets confirm we have the appropriate routs created for us
run a rake routes from the command prompt and you should see these in the
list of all the routes
create_author_for_book POST /books/:book_id/authors(.:format)
{:controller=>"authors", :action=>"create_for_book"}
new_author_for_book GET /books/:book_id/authors/new(.:format)
{:controller=>"authors", :action=>"new_for_book"}
create_book_for_author POST /authors/:author_id/books(.:format)
{:controller=>"books", :action=>"create_for_author"}
new_book_for_author GET /authors/:author_id/books/new(.:format)
{:controller=>"books", :action=>"new_for_author"}
Ok we have the routes now to add them.
Create a books and authors subdir under views.
Create show.dryml in the books dir
<show-page>
<after-collection-section:>
<a:authors action="new" if="&can_create?(BookAuthor)">
<ht key="author.actions.new" count="1">
New Author
</ht>
</a:authors>
</after-collection-section:>
</show-page>
And a show.dryml is authors dir
<show-page>
<after-collection-section:>
<a:books action="new" if="&can_create?(BookAuthor)">
<ht key="book.actions.new" count="1">
New Book
</ht>
</a:books>
</after-collection-section:>
</show-page>
Now if you view a book or an author there is a link to add a new book or
author but they don't quite work yet so on we march.
We need to modify the forms that are auto generated for entering books and
authors. Open up your views/taglibs/applicatoin.dryml and add the
following.
<extend tag="form" for="Author">
<old-form replace>
<field-list: fields="name, books" />
<after-field-list:> <%= hidden_field(:book, :id) %></after-field-list:>
<actions:>
<submit label="#{ht 'author.actions.save', :default=>['Save']}"
param/>
<or-cancel with="&@book" param="cancel"/>
</actions:>
</old-form>
</extend>
<extend tag="form" for="Book">
<old-form replace>
<field-list: fields="title, authors" />
<after-field-list:> <%= hidden_field(:author, :id)
%></after-field-list:>
<actions:>
<submit label="#{ht 'book.actions.save', :default=>['Save']}" param/>
<or-cancel with="&@author" param="cancel"/>
</actions:>
</old-form>
</extend>
now add this to your books_controller.rb
def new_for_author
@author = Author.find_by_id(params[:author_id])
hobo_new
end
def create
@author = Author.find_by_id(params[:author][:id])
hobo_create do
@this.authors=[@author]
redirect_to @author if valid?
end
end
and this to your authors_controller.rb
def new_for_book
@book = Book.find_by_id(params[:book_id])
hobo_new
end
def create
@book = Book.find_by_id(params[:book][:id])
hobo_create do
@this.books=[@book]
redirect_to @book if valid?
end
end
You can now add new books to authors and new authors to books.
Bob
--
You received this message because you are subscribed to the Google Groups "Hobo
Users" group.
To view this discussion on the web visit
https://groups.google.com/d/msg/hobousers/-/d5-JPBLqSeMJ.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/hobousers?hl=en.