[ruby-on-rails] 중첩 된 자원이있는 form_for

form_for 및 중첩 리소스에 대해 두 부분으로 된 질문이 있습니다. 내가 블로그 엔진을 작성 중이고 기사에 댓글을 연결하고 싶다고 가정 해 보겠습니다. 다음과 같이 중첩 된 리소스를 정의했습니다.

map.resources :articles do |articles|
    articles.resources :comments
end

댓글 양식은 다음과 같이 기사 자체 아래에있는 기사의 show.html.erb보기에 있습니다.

<%= render :partial => "articles/article" %>
<% form_for([ :article, @comment]) do |f| %>
    <%= f.text_area :text %>
    <%= submit_tag "Submit" %>
<%  end %>

이것은 오류, “Called id for nil, 이것은 실수로 등이 될 것입니다.” 나는 또한 시도했다

<% form_for @article, @comment do |f| %>

올바르게 렌더링되지만 f.text_area를 댓글 대신 기사의 ‘텍스트’필드와 관련시키고 해당 텍스트 영역의 article.text 속성에 대한 html을 표시합니다. 그래서 나는 이것도 잘못된 것 같습니다. 내가 원하는 것은 ‘제출’이 CommentsController에 대한 생성 작업을 호출하는 양식입니다. 예를 들어 / articles / 1 / comments에 대한 게시 요청과 같이 params에 article_id가 있습니다.

내 질문의 두 번째 부분은 시작하는 주석 인스턴스를 만드는 가장 좋은 방법은 무엇입니까? ArticlesController의 show 작업에서 @comment를 만들고 있으므로 주석 개체는 form_for 도우미의 범위에 있습니다. 그런 다음 CommentsController의 생성 작업에서 form_for에서 전달 된 매개 변수를 사용하여 새 @comment를 생성합니다.

감사!



답변

Travis R이 맞습니다. (나는 당신을 찬성 할 수 있으면 좋겠어요.) 방금이 일을 직접 했어요. 다음 경로로 :

resources :articles do
  resources :comments
end

다음과 같은 경로를 얻습니다.

/articles/42
/articles/42/comments/99

컨트롤러로 라우팅

app/controllers/articles_controller.rb
app/controllers/comments_controller.rb

http://guides.rubyonrails.org/routing.html#nested-resources 에서 말하는 것처럼 특별한 네임 스페이스가 없습니다.

그러나 부분과 형태는 까다로워집니다. 대괄호에 유의하십시오.

<%= form_for [@article, @comment] do |f| %>

가장 중요한 것은 URI를 원한다면 다음과 같은 것이 필요할 수 있습니다.

article_comment_path(@article, @comment)

또는 :

[@article, @comment]

http://edgeguides.rubyonrails.org/routing.html#creating-paths-and-urls-from-objects에 설명 된대로

예를 들어, comment_item반복을 위해 제공된 부분 컬렉션 내부 에서

<%= link_to "delete", article_comment_path(@article, comment_item),
      :method => :delete, :confirm => "Really?" %>

jamuraa가 말하는 것은 Article의 맥락에서 작동 할 수 있지만 다른 다양한 방식으로는 작동하지 않았습니다.

중첩 된 리소스와 관련된 많은 토론이 있습니다. 예 : http://weblog.jamisbuck.org/2007/2/5/nesting-resources

흥미롭게도 저는 대부분의 사람들의 단위 테스트가 실제로 모든 경로를 테스트하는 것은 아니라는 것을 방금 배웠습니다. 사람들이 jamisbuck의 제안을 따를 때 중첩 된 리소스를 얻는 두 가지 방법으로 끝납니다. 그들의 단위 테스트는 일반적으로 가장 간단한 것을 얻거나 게시합니다.

# POST /comments
post :create, :comment => {:article_id=>42, ...}

선호하는 경로를 테스트하려면 다음과 같이해야합니다.

# POST /articles/42/comments
post :create, :article_id => 42, :comment => {...}

내가 이것을 전환했을 때 내 단위 테스트가 실패하기 시작했기 때문에 이것을 배웠습니다.

resources :comments
resources :articles do
  resources :comments
end

이에:

resources :comments, :only => [:destroy, :show, :edit, :update]
resources :articles do
  resources :comments, :only => [:create, :index, :new]
end

중복 경로가 있고 몇 가지 단위 테스트를 놓치는 것은 괜찮다고 생각합니다. (왜 테스트해야합니까? 사용자가 중복을 보지 않더라도 양식에서 암시 적으로 또는 명명 된 경로를 통해 참조 할 수 있기 때문입니다.) 그래도 불필요한 중복을 최소화하려면 다음을 권장합니다.

resources :comments
resources :articles do
  resources :comments, :only => [:create, :index, :new]
end

긴 답변에 대해 죄송합니다. 미묘함을 아는 사람은 많지 않은 것 같습니다.


답변

controller : @post@comment포스트에 대해 두 객체가 모두 생성되었는지 확인하십시오. 예 :

@post = Post.find params[:post_id]
@comment = Comment.new(:post=>@post)

그런 다음보기 :

<%= form_for([@post, @comment]) do |f| %>

위와 같이 쉼표로 구분 된 것이 아니라 form_for에 배열을 명시 적으로 정의해야합니다.


답변

양식에서 특별한 일을 할 필요가 없습니다. show 작업에서 올바르게 주석을 작성하면됩니다.

class ArticlesController < ActionController::Base
  ....
  def show
    @article = Article.find(params[:id])
    @new_comment = @article.comments.build
  end
  ....
end

그런 다음 기사보기에서 양식을 작성하십시오.

<% form_for @new_comment do |f| %>
   <%= f.text_area :text %>
   <%= f.submit "Post Comment" %>
<% end %>

기본적으로,이 댓글은 갈 것 create의 행동 CommentsController이 다음 아마 데려 가고 싶다는 것, redirect :back받는 당신이 그렇게있는 거 라우팅 뒷면에 Article페이지.


답변