【问题标题】:Rails polymorphic posts associations and form_for in viewsRails 多态在视图中发布关联和 form_for
【发布时间】:2014-12-15 00:12:15
【问题描述】:

我在部门视图中为多态“部门”职位设置表单时遇到问题。我遵循了多态关联的 rails-cast 教程here

型号:

   class Course < ActiveRecord::Base
        belongs_to :department, inverse_of: :courses
        has_and_belongs_to_many :users, -> { uniq }
        has_many :posts, as: :postable  #allows polymorphic posts
    end
    class Department < ActiveRecord::Base
        has_many :courses, inverse_of: :department
        has_many :posts, as: :postable  #allows polymorphic posts
        has_and_belongs_to_many :users, -> {uniq}
    end
    class Post < ActiveRecord::Base
        belongs_to :user, touch: true #updates the updated_at timestamp whenever post is saved
        belongs_to :postable, polymorphic: true #http://guides.rubyonrails.org/association_basics.html#polymorphic-associations
        belongs_to :department, counter_cache: true #for counting number of posts in department
        belongs_to :course, counter_cache: true
        validates :department_id, :course_id, presence: true
    end

配置/路由

  devise_for :users
  devise_scope :users do
    match '/users/:id',       to: "users#show",    via: 'get'
  end
  resources :departments do
    resources :courses
    resources :posts
  end
  resources :courses do
    resources :posts
  end

views/departments/show.html.erb

  <div class="tab-pane" id="posts"><br>
    <center><h3>Posts:</h3></center>
    <%= render "posts/form", postable: @department %>
  </div>

views/posts/_form.html.erb

<%= render "posts/wysihtml5" %>
<center><h3>Create New Post:</h3></center>

    <%= form_for [@postable, Post.new] do |f| %>
      <%= f.label :title %>
      <%= f.text_field :title, class: "form-control" %>

      <%= f.label :description %>
      <%= f.text_area :description, :rows => 3, class: "form-control" %>

      <%= f.text_area :content, :rows => 5, placeholder: 'Enter Content Here', class: "wysihtml5" %>

      <span class="pull-left"><%= f.submit "Create Post", class: "btn btn-medium btn-primary" %></span>
   <% end %>

控制器/post_controller.rb

class PostsController < ApplicationController
    before_filter :find_postable
    load_and_authorize_resource 

    def new
        @postable = find_postable
        @post = @postable.posts.new
    end

    def create
        @postable = find_postable
        @post = @postable.posts.build(post_params)

        if @post.save
            flash[:success] = "#{@post.title} was sucessfully created!"
            redirect_to department_post_path#id: nil        #redirects back to the current index action
        else
            render action: 'new'
        end
    end

    def show
        @post = Post.find(params[:id])
    end

    def index
        @postable = find_postable
        @posts = @postable.posts
    end
...
    private
    def post_params
        params.require(:post).permit(:title, :description, :content)
    end

    def find_postable   #gets the type of post to create
        params.each do |name, value|
            if name =~ /(.+)_id$/
                return $1.classify.constantize.find(value)
            end
        end
        nil
    end

控制器/departments_controller.rb

def show
    id = params[:id]
    @department = Department.find(id)

    @course = Course.new
    @course.department_id = @department
end

错误是“# 的未定义方法`posts_path'”

我认为错误与表单中的路径有关,但我不知道是什么。我也尝试过[@postable, @postable.posts.build],但这只是给了我未定义的方法:PostsController

有谁知道发生了什么以及我该如何解决?

【问题讨论】:

    标签: ruby-on-rails forms views posts polymorphism


    【解决方案1】:

    @department 作为局部变量传递到表单部分,但表单调用实例变量

    # views/departments/show.html.erb
    <%= render "posts/form", postable: @department %> # <------ postable
    
    # views/posts/_form.html.erb
    <%= form_for [@postable, Post.new] do |f| %>      # <------ @postable
    

    因此,命名空间路由没有正确确定

    [@postable, Post.new]  # => departments_posts_path
    [   nil   , Post.new]  # => posts_path
    

    检查您的路线,帖子只能通过嵌套路线访问。 posts_path 不是有效路由,它的方法不存在,错误是正确的:undefined method `posts_path'


    修复:

    在部门控制器中设置一个@postable 实例变量,以便表单助手可以使用它:

    def show
        id = params[:id]
        @postable, @department = Department.find(id)  # <-- add @postable
    
        @course = Course.new
        @course.department_id = @department
    end
    

    然后你可以简单地在视图中调用render:

    <%= render "posts/form" %> 
    

    【讨论】:

    • 非常感谢,这确实有助于清除我遇到的错误。但是现在当我提交表单时,它会点击 PostsController 中的 create 方法,但不满足“if @post.save”条件,因此它会呈现新的操作和相应的视图。显然我希望它保存,然后重定向到部门显示页面(department_path)或部门帖子查看页面(department_post_path)。为什么不保存??再次感谢您的帮助!
    • 此验证将始终失败:validates :department_id, :course_id, presence: true。它检查是否存在 both ID,鉴于多态关联,这是不可能的。你想要一个或另一个但不是两个,或XOR。看到这个问题:stackoverflow.com/questions/2134188/…
    • 谢谢!这样就解决了,我让帖子正常工作了。非常感谢。
    猜你喜欢
    • 2014-02-13
    • 1970-01-01
    • 2019-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多