这个表单路由有什么问题吗?
我有一个用户模型和一个书籍模型。用户可以阅读书籍(作为读者),这会在阅读模型中创建一个条目:
id | reader_id | book_id
用户还有一个他们已阅读的书籍列表。这些存储在红色(我使用红色是因为“读”这个词的现在时和过去时是相同的)模型中,该模型看起来与上面的阅读模型相同。
现在,当用户正在阅读一本书时,我想显示一个代表完成这本书的按钮。
完成操作位于 ReadingsController 中,如下所示:
def finish
@book = current_user.readings.find(params[:id]).book
current_user.stop_reading!(@book)
current_user.make_red! @book
redirect_to :back
end
正如您可能知道的那样,这会获取 Readings 表中记录的 id,销毁它并在记录书籍的表中创建一条新记录红色。
“完成阅读”按钮的表单助手当前如下所示:
<%= form_for :reading, current_user.readings.find_by_book_id(book.id), :url => { :controller => :readings, :action => "finish" }, :method => :delete do |f| %>
<div class="actions"><%= f.submit button_text %></div>
<% end %>
但由于某种原因,这会呈现一个具有错误 id 的表单,因为“9781440506604”不是读数表中记录的 id,它是书籍表(准确地说是一本书的 ISBN-13)。
<form accept-charset="UTF-8" action="/readings/9781440506604/finish" method="post">
</form>
我做错了什么?
编辑添加reading.rb
class Reading < ActiveRecord::Base
attr_accessible :book_id
# one person reading a new book may cause feed_item creations in multiple users feeds
has_many :feed_items, :as => :event
has_many :comments, :as => :parent, :dependent => :destroy
scope :from_users_followed_by, lambda { |user| followed_by(user) }
# need to pass the class name here because there is no Reader model
belongs_to :reader, :class_name => "User"
belongs_to :book
validates :reader_id, :presence => true
validates :book_id, :presence => true
def self.followed_by(user)
...
end
end
# and user.rb
class User < ActiveRecord::Base
attr_accessible :name, :email, :password, :password_confirmation, :avatar, :remember_me, :avatar_url
has_many :readings, :dependent => :destroy,
:foreign_key => "reader_id"
has_many :reads, :through => :readings, :source => :book
has_many :reds, :foreign_key => "reader_id",
:dependent => :destroy
has_many :red, :through => :reds, :source => :book
def reading? book
self.readings.find_by_book_id(book)
end
def read! book
self.readings.create!(:book_id => book.id)
end
def stop_reading! book
self.readings.find_by_book_id(book).destroy
end
def red? book
self.reds.find_by_book_id(book)
end
def make_red! book
unless red? book
self.reds.create!(:book_id => book.id)
end
end
end
顺便说一句,我尝试创建一个正在阅读书籍1的用户并在控制台中执行user.readings.find_by_book_id(1),它从阅读表中返回一条记录。
按要求
# routes.rb
resources :readings, :only => [:create, :destroy, :show] do
member do
post :create_comment
delete :finish
end
end
I have a users model and a book model. Users can read books (as a reader) which creates an entry in the Readings model:
id | reader_id | book_id
Users also have a list of books that they have read. These are stored in the Red (I use Red because the present and past tense of the word 'read' are the same) model which looks the same as the Reading model above.
Now when a user is reading a book, I would like to display a button which represents finishing the book.
The finish action is in the ReadingsController and looks like this:
def finish
@book = current_user.readings.find(params[:id]).book
current_user.stop_reading!(@book)
current_user.make_red! @book
redirect_to :back
end
As you can probably tell, this takes in the id of a record in the readings table, destroys it and makes a new record in the table for recording books red.
The form helper for the "Finish Reading" button currently looks like this:
<%= form_for :reading, current_user.readings.find_by_book_id(book.id), :url => { :controller => :readings, :action => "finish" }, :method => :delete do |f| %>
<div class="actions"><%= f.submit button_text %></div>
<% end %>
But for some reason this renders a form with the wrong id because "9781440506604" is not the id of a record in the readings table, it's the id of a record in the books table (the ISBN-13 of a book to be precise).
<form accept-charset="UTF-8" action="/readings/9781440506604/finish" method="post">
</form>
What is it I'm doing wrong?
EDIT to add reading.rb
class Reading < ActiveRecord::Base
attr_accessible :book_id
# one person reading a new book may cause feed_item creations in multiple users feeds
has_many :feed_items, :as => :event
has_many :comments, :as => :parent, :dependent => :destroy
scope :from_users_followed_by, lambda { |user| followed_by(user) }
# need to pass the class name here because there is no Reader model
belongs_to :reader, :class_name => "User"
belongs_to :book
validates :reader_id, :presence => true
validates :book_id, :presence => true
def self.followed_by(user)
...
end
end
# and user.rb
class User < ActiveRecord::Base
attr_accessible :name, :email, :password, :password_confirmation, :avatar, :remember_me, :avatar_url
has_many :readings, :dependent => :destroy,
:foreign_key => "reader_id"
has_many :reads, :through => :readings, :source => :book
has_many :reds, :foreign_key => "reader_id",
:dependent => :destroy
has_many :red, :through => :reds, :source => :book
def reading? book
self.readings.find_by_book_id(book)
end
def read! book
self.readings.create!(:book_id => book.id)
end
def stop_reading! book
self.readings.find_by_book_id(book).destroy
end
def red? book
self.reds.find_by_book_id(book)
end
def make_red! book
unless red? book
self.reds.create!(:book_id => book.id)
end
end
end
By the way I tried making a user who is reading book 1 and doing user.readings.find_by_book_id(1) in the console and it returns a record from the readings table.
as requested
# routes.rb
resources :readings, :only => [:create, :destroy, :show] do
member do
post :create_comment
delete :finish
end
end
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
看起来您的
Reading
模型中有to_param
方法尝试清楚地调用 id:
UPD
:only =>; [:create, :destroy, :show]
在你的路由中<%= form_for :reading, current_user.readings.find_by_book_id(book.id), :url =>; {:控制器=> :读数,:行动=> “完成”,:id => current_user.readings.find_by_book_id(book.id).id }, :html =>; {:方法=> :删除} 做 |f| %>
Looks like you have got
to_param
method in yourReading
modeltry to call id clearly:
UPD
:only => [:create, :destroy, :show]
from your routes<%= form_for :reading, current_user.readings.find_by_book_id(book.id), :url => { :controller => :readings, :action => "finish", :id => current_user.readings.find_by_book_id(book.id).id }, :html => {:method => :delete} do |f| %>
我对 Rails 3 不是特别了解(仍在使用 Rails 2),但是您不应该向
:url
参数传递更多信息吗?这似乎没有提及任何有关您要发布到的 ID 的信息:
难道不应该更接近这个吗:(
假设
reading_id
替换为实际 ID)I'm not particularly knowledgeable about rails 3 (still using rails 2), but shouldn't you be passing more information to the
:url
param?This doesn't seem to mention anything about the ID you want to post to:
Shouldn't it be something closer to this:
(Assuming
reading_id
to be substituted for the actual ID)