在我的Rails应用中,我有invoices
,而projects
可以有很多class Invoice < ActiveRecord::Base
attr_accessible :project_id
end
。
模型:
class InvoicesController < ApplicationController
before_filter :authorized_user, :only => [ :show, :edit, :destroy ]
before_filter :authorized_project, :only => [ :create, :update ]
def create # safe
@invoice = @project.invoices.build(params[:invoice])
if @invoice.save
flash[:success] = "Invoice saved."
redirect_to edit_invoice_path(@invoice)
else
render :new
end
end
def update # not safe yet
if @invoice.update_attributes(params[:invoice])
flash[:success] = "Invoice updated."
redirect_to edit_invoice_path(@invoice)
else
render :edit
end
end
private
def authorized_user
@invoice = Invoice.find(params[:id])
redirect_to root_path unless current_user?(@invoice.user)
end
def authorized_project
@project = Project.find(params[:invoice][:project_id])
redirect_to root_path unless current_user?(@project.user)
end
end
控制器:
invoice
我最担心的是恶意用户有一天可能会创建属于另一个用户的project
的{{1}}。
现在感谢这个董事会中一些人的帮助,我设法提出before_filter
,确保项目创建时不会发生这种情况。
问题是我不明白如何将此过滤器应用于update
操作。
由于更新操作未使用Rails的build
函数,因此我根本不知道如何在其中获取@project
。
有人可以帮忙吗?
答案 0 :(得分:1)
在您的情况下,我会从current_user
开始,而不是@project
(提供User
has_many :invoices
):
current_user.invoices.build(params[:invoice])
您也可以执行以下操作,而不是明确检查current_user?(@invoice.user)
:
def find_invoice
@invoice = current_user.invoices.find(params[:id])
end
def find_project
@project = current_user.projects.find(params[:invoice][:project_id])
end
错误的发票或项目将抛出您可能或可能不想处理的500。
如果User
has_many :invoices, :through => :projects
和Project
因此has_many :invoices
那么:
def find_invoice
@invoice = @project.invoices.find(params[:id])
end
答案 1 :(得分:0)
@project.invoices.build
方法会创建一个与该特定Invoice
自动关联的新@project
。您不必做任何工作,也不存在将其链接到错误项目的风险。
但是,您需要确保project_id
不是可访问的属性。