在轨道中传递参数...理解参数的突破

时间:2012-12-02 00:02:50

标签: ruby-on-rails-3 params

我有一个简单的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

2 个答案:

答案 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用来分配这些值的网址参数。哇!有什么突破......