我有一个简单的has_many belongs_to关系,我想为belongs_to模型的视图包含父对象,我已经取得了一些成功,但我希望它能更好地工作。
class Submission < ActiveRecord::Base
belongs_to :user
belongs_to :contest
end
class Contest < ActiveRecord::Base
belongs_to :user
has_many :submissions, :dependent => :destroy
end
在有效的情况下,我将contest_id传递给提交,方法是将其放入网址:
<%= link_to 'Submit Contest Entry', new_submission_path(:contest_id => @contest.id),
:class => 'btn btn-primary btn-large mleft10' %>
这样,结合hidden_field:
<%= f.hidden_field :contest_id %>
控制器中的find_contest方法(使用before_filter调用):
def find_contest
#the next line is giving the error (line 76)
@contest = Contest.find(params[:submission][:contest_id])
end
使其适用于提交/新提交,但是如何向控制器添加一个只能在多个页面上工作的查找,就像我想要在show和index中访问一样。现在,我收到一个错误:
Started GET "/submissions?contest_id=5" for 127.0.0.1 at 2012-12-01 16:01:45 -0800
Processing by SubmissionsController#index as HTML
Parameters: {"contest_id"=>"5"}
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = 2 ORDER BY users.created_at DESC LIMIT 1
Completed 500 Internal Server Error in 37ms
NoMethodError (undefined method `[]' for nil:NilClass):
app/controllers/submissions_controller.rb:76:in `find_contest'
[编辑] 为提交添加show动作:
before_filter :find_contest, :except => [:index, :show, :edit, :update, :destroy]
def find_contest
@contest = Contest.find(params[:submission][:contest_id])
end
def show
contest_id = @submission.contest_id
@submission = @commentable = Submission.find(params[:id])
@comments = @commentable.comments.order(:created_at).reverse
respond_to do |format|
format.html # show.html.erb
format.json { render :json => @submission }
end
end
答案 0 :(得分:0)
您正在访问控制器 SubmissionsController 的操作索引;我假设您在行动索引内部调用方法 find_contest 。错误是因为在 find_contest 方法中你试图得到 params [:submission] [:contest_id] 的值,但是这样的param不存在;你得到的参数是 params [:contest_id] 。
通过许多操作管理相同方法可以做的是更改方法并传递参数,如下所示:
def find_contest(contest_id)
@contest = Contest.find(contest_id)
end
def index
find_contest(params[:contest_id])
#some other code...
end
但是,如果您使用的是 before_filter 之类的内容,如果 params [:contest_id] .nil? find_contest 方法内部>如果不是零则使用它,否则使用 params [:submission] [:contest_id] 。
答案 1 :(得分:0)
这是这个问题的答案,但是我已经为索引和show使用了两行,它们可能被重构为一个(编辑注释:Pablo89建议显示一个重构,包含但是索引仍然是两行)
这两条线在两种情况下都非常重要,特别是初学者,这就是原因:
为了将parent_id(contest_id)传递到相关视图(显示提交),我使用params中的submission_id定义了@submission(@associated)(可评论在那里用于其他目的,可以忽略)。
@submission = @commentable = Submission.find(params[:id])
在网站地址中可以找到参数:在这种情况下:
http://localhost:3000/submissions/41
41是submission_id。这很明显。
Rails使用浏览器窗口中的页面地址来分配实例值。我之前不知道Rails在哪里找到params,因为Rails会自动执行很多操作。 params是网页地址。 DOH!
然后我使用@ submission的contest_id键分配了contest_id,作为belongs_to协会的一部分,并使用find来访问@contest
contest_id = @submission.contest_id
@contest = Contest.find(contest_id)
正如Pablo89指出的那样,由于轨道关联能力,有两条线可以减少为一条:
@contest = @submission.contest
在索引中,没有@submission,所以我将contest_id传递给此页面,通过link_to该页面,在两个地方找到竞赛/ show和提交/ show:
<%= link_to 'Browse All Submissions', submissions_path(:contest_id => @contest.id), :class => 'btn btn-mini pull-right' %>
点击该链接会转到提交/索引并生成以下地址:
http://localhost:3000/submissions?contest_id=4
(:contest_id =&gt; @ contest.id)将?contest_id = 4添加到地址,以便我可以通过“params”从提交控制器访问它
对于像我这样的初学者来说,这是建立对params理解的重要方法,因为页面的地址是Rails从@submission或@contest分配实例变量的地方。
嵌套路线如下所示:
比赛/ 5 / submssions / 41
如果您使用嵌套路线,比赛和提交值都在地址中,就在那里,等待使用!这个地址也被称为“params”,(我重复它以便让其他学习者像我一样有厚厚的头骨),但是如果你没有使用嵌套路线,那么父ID必须以另一种方式传递,比如添加它是上面例子中的link_to。
从那里开始,要访问?contest_id = 4,我将以下内容放在提交的索引操作中:
contest_id = params[:contest_id]
@contest = Contest.find(contest_id)
这对我来说是一个突破,因为到目前为止,我从来不知道什么是params或它是如何工作的,只是它有效。
通过理解这个基本概念,大多数有经验的开发人员都非常清楚他们没有想到,我对控制器了解得更多。
我在这里传达的所有内容可能也可能不正确,但我希望这对其他初学者有帮助。我现在对自己解决问题的能力感到非常自信。在此之前我使用params做的很多事情是尝试不同的方式,直到它没有任何基本的理解。它现在让我开怀大笑,因为它真的很简单。我认为params这个词有些强大,因为它可以在任何地方引用任何参数。
现在我知道,这是Rails用来分配这些值的网址参数。哇!有什么突破......