Rails:在其他模型的show动作中创建新帖子

时间:2012-06-13 14:40:26

标签: ruby-on-rails ruby-on-rails-3

有几个地点,人们可以撰写有关这些地点的帖子。所以我到目前为止所做的是创建了一个表格位置(rails generate scaffold locations name:string)和一个表格(rails generate scaffold posts title:string text:string author:string image:string location_id:integer)。因此表posts具有表locations的外键。因此,可以在表格的show动作中查看帖子。

查看/ locations / 1(显示位置模型的操作)和查看/ posts / new:

View for /locations/1 (show action of the location model) enter image description here

我想要的是访问某个特定位置的人可以创建帖子而无需填写ID框,如下所示。它应该自动知道此帖子属于具有当前ID的位置。我需要在控制器中更改什么以及我在html.erb文件中需要做什么才能正常工作?我已经试过了......但是它检索了一个noMethod错误。

  def newpost
    @post = current_location.posts.build 

    respond_to do |format|
      format.html 
      format.json { render json: @locations }
    end
  end 

所以我遵循了Charles和Zajn的指示。

class PostsController < ApplicationController
(...)
  def new
    #@post = Post.new
    @post = @location.posts.build

    respond_to do |format|
      format.html # new.html.erb
      format.json { render json: @post }
    end
  end
(...)
end
config/routes.rb

中的

resources :locations do
  resources :posts
end

帖子部分

<%= form_for @post do |f| %>
  <%= f.label :title, 'Title' %>
  <%= f.text_field :title %>

  <%= f.label :title, 'Text' %>
  <%= f.text_field :text%>

  <%= f.label :title, 'Author' %>
  <%= f.text_field :author %>

  <%= f.hidden_field :location_id %>
  <%= f.submit "Submit" %>
<% end %>

并且似乎仍然存在错误:

NoMethodError in PostsController#new

详细信息:

undefined method `posts' for nil:NilClass
app/controllers/posts_controller.rb:28:in `new'

Request
Parameters:
{"location_id"=>"1"}

Response
Headers:
None

第二次尝试:现在我编辑了PostsController

  def new
    #@post = Post.new
    @location = Location.find(params[:location_id]) # You can move this to a before_filter, if you prefer
    @post = @location.posts.build

    respond_to do |format|
      format.html # new.html.erb
      format.json { render json: @post }
    end
  end

似乎控制器中没有错误了。现在NoMethodError - 文件中有一些html.erb

undefined method 'posts_path' for #<#<Class:0x2404384>:0x204ed98>

1: <%= form_for @post do |f| %>
2:     <%= f.label :title, 'Title' %>
3:     <%= f.text_field :title %>
4: 

app/views/posts/_form.html.erb:1:in `_app_views_posts__form_html_erb___1061496502_7409780'
app/views/posts/new.html.erb:3:in `_app_views_posts_new_html_erb__238125222_5750540'
app/controllers/posts_controller.rb:31:in `new'

我的_form.html.erb

<%= form_for @post do |f| %>
    <%= f.label :title, 'Title' %>
    <%= f.text_field :title %>

    <%= f.label :title, 'Text' %>
    <%= f.text_field :text%>

    <%= f.label :title, 'Author' %>
    <%= f.text_field :author %>

    <%= f.hidden_field :location_id, :value => @location.id %>
    <%= f.submit "Submit" %>
<% end %>

我的new.html.erb

<h1>New post</h1>

<%= render 'form' %>

<%= link_to 'Back', posts_path %>

我已经尝试简单地删除最后一个代码<%= link_to 'Back', posts_path %>,它仍然检索错误,即使我保存了所有内容,关闭服务器并重新打开它。但我认为问题不在于posts_path。因为如果我将html.erb文件中的<%= form_for @post do |f| %>更改为<%= form_for @location.post do |f| %>,则会检索NoMethodError for 'post'

2 个答案:

答案 0 :(得分:3)

听起来您希望帖子位于nested resource下的位置。

如果这是你要做的事情,那么在config/routes.rb,你应该有:

resources :locations do
  resources :posts
end

为id = 1的位置创建新帖子的网址为/locations/1/posts/newnew中的PostsController操作应如下所示:

def new
  @location = Location.find(params[:location_id]) # You can move this to a before_filter, if you prefer
  @post = @location.posts.build

  respond_to do |format|
    format.html
    format.json { render json: @post }
  end
end

您的app/views/posts/_form.html.erb部分内容应如下所示:

<%= form_for [@location, @post] do |f| %>
  <%= f.label :title, 'Title' %>
  <%= f.text_field :title %>

  <%= f.label :title, 'Text' %>
  <%= f.text_field :text%>

  <%= f.label :title, 'Author' %>
  <%= f.text_field :author %>

  <%= f.hidden_field :location_id %>
  <%= f.submit "Submit" %>
<% end %>

请注意,对于嵌套资源,您在视图中使用的路径助手是不同的。例如,要获取属于指定位置的帖子的index操作的路径,您可以使用location_posts_path(@location),而不是posts_path

答案 1 :(得分:2)

您只需在创建帖子的表单中添加一个包含该位置ID的隐藏字段。

所以,像这样:

<%= form_for @post do |f| %>
    <%= f.label :title, 'Title' %>
    <%= f.text_field :title %>

    <%= f.label :title, 'Text' %>
    <%= f.text_field :text%>

    <%= f.label :title, 'Author' %>
    <%= f.text_field :author %>

    <%= f.hidden_field :location_id, :value => @location.id %>
    <%= f.submit "Submit" %>
<% end %>

其中@location是包含您正在查看的当前位置的实例变量。