这个表单路由有什么问题吗?

发布于 2024-10-30 23:39:35 字数 2874 浏览 1 评论 0原文

我有一个用户模型和一个书籍模型。用户可以阅读书籍(作为读者),这会在阅读模型中创建一个条目:

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

So尛奶瓶 2024-11-06 23:39:35

看起来您的 Reading 模型中有 to_param 方法

尝试清楚地调用 id:

current_user.readings.find_by_book_id(book.id).id

UPD

  1. 删除 :only =>; [:create, :destroy, :show] 在你的路由中
  2. 使用这个 <%= 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 your Reading model

try to call id clearly:

current_user.readings.find_by_book_id(book.id).id

UPD

  1. remove :only => [:create, :destroy, :show] from your routes
  2. use this <%= 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| %>
酷炫老祖宗 2024-11-06 23:39:35

我对 Rails 3 不是特别了解(仍在使用 Rails 2),但是您不应该向 :url 参数传递更多信息吗?

这似乎没有提及任何有关您要发布到的 ID 的信息:

:url => { :controller => :readings, :action => "finish" }

难道不应该更接近这个吗:(

:url => { :controller => :readings, :action => "finish", :id => reading_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:

:url => { :controller => :readings, :action => "finish" }

Shouldn't it be something closer to this:

:url => { :controller => :readings, :action => "finish", :id => reading_id }

(Assuming reading_id to be substituted for the actual ID)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文