如何用has_many来定义params?

时间:2016-04-20 14:04:26

标签: ruby-on-rails ruby

我正在使用has_many通过关系,我真的没有得到我应该做的其他工作。 我想有一些我不理解和省略的参数。如果是这样,请告诉我在哪里以及如何写它,因为我因为所有这些参数而感到困惑。 book.rb:

class Book < ActiveRecord::Base
  has_many :user_books
  has_many :users, through: :user_books
end

user.rb:

class User < ActiveRecord::Base
  devise :database_authenticatable, :registerable, :confirmable,
    :recoverable, :rememberable, :trackable, :validatable

  validates :full_name, presence: true

  has_many :user_books
  has_many :books, through: :user_books #books_users - book_id user_id

end

和books_controller.rb:

class BooksController < ApplicationController
  before_action :is_admin?, except: [:show_my_books, :book_params]
  before_filter :authenticate_user!
  expose(:book, attributes: :book_params)
  expose(:user_book)
  expose(:user_books)
  expose(:books){current_user.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 show
  end

  def is_admin?
    if current_user.admin?
      true
    else
      render :text => 'Who are you to doing this? :)'
    end
  end

  def book_params
    params.require(:book).permit(:name, :author, :anotation, user:[:name])
  end
end

当我创建新书时,它会给我一个错误

  

无法找到“id”= 27 [WHERE“user_books”。“”u​​ser_id“=?]

     

<%=book.name%>

对于一个愚蠢的问题感到抱歉,但我找不到一个正确的例子来了解它,这就是我向你寻求帮助的原因。感谢您的每一个帮助,谢谢!

1 个答案:

答案 0 :(得分:2)

要通过表单设置关系,您通常使用选择或复选框并传递相关项目的ID:

对于一对一的关系,请求看起来像这样:

POST /books  { book: { name: 'Siddharta', author: 'Herman Hesse', user_id: 1 } }

对于多对多或一对多,您可以使用_ids

POST /books  { book: { name: 'Siddharta', author: 'Herman Hesse', user_ids: [1,2,3] } }

ActiveRecord为relation_name_ids=和HABTM关系创建一个特殊的has_many setter和getter。它允许您通过传递ID数组来修改对象的关系。

您可以像这样创建表单输入:

<%= form_for(@book) do |f| %>
  <%= f.collection_select(:author_ids, User.all, :id, :name, multiple: true) %>

   OR

   <%= f.collection_checkboxes(:author_ids, User.all, :id, :name) %>
<% end %>

要将允许标量值数组而不是嵌套哈希值的user_ids参数列入白名单,我们会传递一个空数组:

def book_params
  params.require(:book).permit(:name, :author, :anotation, user_ids: [])
end

另一方面,如果你想将记录分配给当前用户,最好从会话或令牌中获取用户,并避免传递参数:

def create
  @book = current_user.books.new(book_params)
  # ...
end

这可以避免恶意用户传递其他用户ID或通过传递自己的ID来控制资源的非常简单的黑客攻击。

至于你的其他错误,为什么它会尝试创建一个奇怪的查询,需要某种堆栈跟踪或日志。

然而,如果你是Rails的新手,你可能想要在适当的曝光宝石上稍微停下来。它掩盖了魔法&#34;魔术&#34;中的许多重要概念。 - 并且你会花更多的时间来弄清楚它是如何工作的,可以更好地学习如何构建好的rails应用程序。