开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜