如何使用 link_to 从控制器调用方法?

How to call a method from controller using link_to?

我希望我的应用在他单击 link 时向 current_user 添加一本书。我的代码似乎没问题,没有错误,但是在用户点击 link 之后什么也没有发生。

book.rb:

has_many :book_users
has_many :users, through: :book_users

user.rb:

has_many :book_users
has_many :books, through: :book_users

book_user.rb:

belongs_to :book
belongs_to :user

books_controller.rb:

before_action :is_admin?, except: [:book_params, :add_to_books_i_read, :index]
before_filter :authenticate_user!
expose(:book, attributes: :book_params)
expose(:books)


  def create
    if book.save
      redirect_to(book)
    else
      render :new
    end
  end

  def update
    if book.save
      redirect_to(book)
    else
      render :edit
    end
  end

  def add_to_books_i_read(book_id)
    current_user.books << Book.find(book_id)
  end

在我的索引视图中我有

ul
  -books.each do |book|
    li
      = link_to "#{book.name}", book_path(book)
      = link_to "  Add to my books", {:controller => "books", method: :add_to_books_i_read, book_id: :book.id}

那么,我做错了什么?为什么我的方法 add_to_books_i_read 什么都不做?单击此 link_to 后,数据库 book_users 中的 table 不会记录任何内容,但它本身运行良好(我通过控制台检查过)。我能做什么?如何让用户通过该方法添加图书以及如何正确调用该方法?我们将不胜感激,谢谢!

  = link_to "  Add to my books", {:controller => "books", action: :add_to_books_i_read, book_id: :book.id}

首先,link_to中的methodsymbol of HTTP verb所以你不能在控制器中传递你的函数 要在您的控制器上定义和使用新操作,您需要为该控制器定义路由 see here

由于 add_to_books_i_read 是一个控制器操作方法,您应该更新您的路由以包含针对 books 资源的此操作,以便与 Rails方法。您还可以为此路径使用 URL 帮助器,如下所示:

/books/:id/add_to_books_i_read

您的代码可能如下所示:

# config/routes.rb
resources :books do
  get :add_to_books_i_read, on: :member
end

# app/controller/books_controller.rb
def add_to_books_i_read
  current_user.books << Book.find(params[:id])
  # redirect or other logic
end

# app/views/books/index.html.haml
ul
  - books.each do |book|
    li
      = link_to "#{book.name}", book_path(book)
      = link_to "Add to my books", add_to_books_i_read_book_path(book)

也尝试将您的路线组织为(注意会员部分)

resources :books do 
  member do
    get :add_to_books_i_read
  end
end

并查看 rake 路由输出中的 Prefix Verb 列。

来自@Ioannis Tziligkakis,我做了一些编辑。

尝试:

# config/routes.rb
resources :books do
  member do
    get :add_to_books_i_read
  end
end

# app/controller/books_controller.rb
def add_to_books_i_read
  current_user.books << Book.find(params[:id])
  # redirect or other logic
end

# app/views/books/index.html.haml
ul
  - books.each do |book|
    li
      = link_to "#{book.name}", book_path(book)
      = link_to "Add to my books", add_to_books_i_read_book_path(book.id)

试试这个:

# config/routes.rb
resources :books do
  # just not about method:
  # use get for request, search
  # use put for update
  # use post for create
  # use delete for destroy
  put :add_to_books_i_read, on: :member
end

# app/controller/books_controller.rb
def add_to_books_i_read
  @book = Book.find(params[:id])
  current_user.books << @book
  respond_to do |format|
    format.js
  end
end

# app/views/books/index.html.haml
ul
  - books.each do |book|
    li{:id => "book_#{book.id}"}
      = render "links", book: book

# add field: app/views/books/_links.html.haml
= link_to "#{book.name}", book_path(book)
= link_to "Add to my books", add_to_books_i_read_book_path(book), method: :put, remote: true

# add field: app/views/books/add_to_books_i_read.js.erb
$("#book_<%= @book.id %>").html("<%= j render 'books/links', book: @book %>")

天哪。在您的建议帮助下,我终于明白了!所以,

控制器:

def add_to_books_i_read
    current_user.books << Book.find(params[:id])
    redirect_to(:back) #this line
end

在路线中

resources :books do
    member do
      get :add_to_books_i_read
    end
end

索引视图

-books.each do |book|
    li
      = link_to "#{book.name}", book_path(book)
      = link_to  "       Add to my books", add_to_books_i_read_book_path(book)

谢谢大家的帮助!我真的真的很感激! :)