Ruby on Rails dropdown values not saving
I'm new to RoR and having an issue when trying to save from multiple dropdowns. I have three objects - books, genres, and authors. A book object has a genre and author associated to it, but the issue is I can only manage to save either a genre or author to my book object, and not both. Here's where I'm at:
class Author < ActiveRecord::Base
validates :name, :presence => true
validates :biography, :presence => true
has_many :books
end
class Genre < ActiveRecord::Base
validates :description, :presence => true
has_many :books
end
class Book < ActiveRecord::Base
belongs_to :genre
belongs_to :author
has_many :cartitems
validates :name, :presence => true
validates :price, :presence => true
validates :description, :presence => true
end
Controller:
def create
#@book = Book.new(params[:book])
@author = Author.find(params[:author].values[0])
@genre = Genre.find(params[:genre].values[0])
@book = @author.books.create(params[:book])
#one or the other saves, but not both
#@book = @genre.books.create(params[:book])
respond_to do |format|
if @book.save
format.html { redirect_to(@book, :notice => 'Book was successfully created.') }
format.xml { render :xml => @book, :status => :created, :location => @book }
else
format.html { render :action => "new" }
format.xml { render :xml => @book.errors, :status => :unprocessable_entity }
end
end
end
Not sure if this will help out or not, but here's what the dropdowns look like in the View:
<div class="field">
<%= f.label :genre %><br />
<%= @items = Genre.find(:all)
select("genre", "description", @items.map {|u| [u.description,u.id]}, {:include_blank => true})%>
Appreciate any help with this.
EDIT - Here's my full form.
<%= form_for(@book) do |f| %>
<% if @book.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@book.errors.count, "error") %> prohibited this book from being saved:</h2>
<ul>
<% @book.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :price %><br />
<%= f.text_field :price %>
</div>
<div class="field">
<%= f.label :description %><br />
<%= f.text_area :description %>
</div>
<div class="field">
<%= f.label :genre %><br />
<%= @items = Genre.find(:all)
select("genre", "description", @items.map {|u| [u.description,u.id]}, {:include_blank => true})%>
</div>
<div class="field">
<%= f.label :author %><br />
<%=@items = Author.find(:all)
select("author", "name", @items.map {|u| [u.name,u.id]}, {:include_blank => true}) %>
</div>
<开发者_StackOverflow社区div class="actions">
<%= f.submit %>
</div>
<% end %>
Update your select fields to be defined like this:
<div class="field">
<%= f.label :genre %><br />
<%= f.select( :genre_id, Genre.all.map {|u| [u.description,u.id]}, {:include_blank => true}) %>
</div>
<div class="field">
<%= f.label :author %><br />
<%= f.select( :author_id, Author.all.map {|u| [u.name,u.id]}, {:include_blank => true}) %>
</div>
And your controller action should be like this:
def create
@book = Book.new(params[:book])
respond_to do |format|
if @book.save
format.html { redirect_to(@book, :notice => 'Book was successfully created.') }
format.xml { render :xml => @book, :status => :created, :location => @book }
else
format.html { render :action => "new" }
format.xml { render :xml => @book.errors, :status => :unprocessable_entity }
end
end
Also, remove the format.xml calls if you don't need them, they're just cluttering your controller action.
There are lots of different ways to fix your problem, it would help to see exactly what's in your params
hash and what your full form looks like, but no matter. Here is one way:
@book = @author.books.create(:genre => @genre)
Here is another (essentially the same thing):
@book = @author.books.create {|book| book.genre = @genre}
You could also instantiate the book separately:
@author = Author.find(params[:author].values[0])
@genre = Genre.find(params[:genre].values[0])
@book = Book.create(:author => @author, :genre => @genre)
My guess is you didn't quite build your form correctly, otherwise your params hash would look similar to this {:book => {:author => 1, :genre => 5}}
and you would be able to do this:
@book = Book.create(params[:book])
And you would not look up the author using params[:author]
, but would instead do params[:book][:author]
if you needed to do it at all.
精彩评论