Ruby on rails 多态注释,注释验证失败时如何呈现?

Ruby on rails 多态注释,注释验证失败时如何呈现?,ruby-on-rails,Ruby On Rails,我创建了一个应用程序,它有多个模型(比如A、B),这些模型与一个评论模型有多态性关联。当查看和控制器关联的页面时,显示操作,和对象关联的注释显示为创建新对象的表单。所有这些都很有效,类似于Ryan Bates在rails网站上发布的15分钟博客。但是,如果我添加验证以确保用户不会提交空白注释,我不确定如何呈现该注释。以下是我的评论控制器中的内容: before_filter :load_resources, :only => [:create] def create if @comme

我创建了一个应用程序,它有多个模型(比如A、B),这些模型与一个评论模型有多态性关联。当查看和控制器关联的页面时,显示操作,和对象关联的注释显示为创建新对象的表单。所有这些都很有效,类似于Ryan Bates在rails网站上发布的15分钟博客。但是,如果我添加验证以确保用户不会提交空白注释,我不确定如何呈现该注释。以下是我的评论控制器中的内容:

before_filter :load_resources, :only => [:create]
def create
  if @comment.save
    redirect_to @back
  else
    render @action
  end
end

private

def load_resources
  @comment = Comment.new(params[:comment])
  case @comment.commentable_type
  when 'A'
    @a = A.find(params[:a_id]
    @comments = @a.comments
    @back = a_url(@comment.commentable_id)
    @resource = @a
    @action = 'as/show'
  when 'B'
    ...
  end
end
before_filter :fetch_post

    def show
      @comment = @commentable.comments.build
    end

    protected
      def fetch_post
        @post = @commentable = Post.find(params[:id])
      end
def create
  @commentable = find_commentable
  # Not sure what the relationship between the base parent and the creator and editor are so I'm going to merge in params in a hacky way
  @comment = @commentable.comments.build(params[:comment]).merge({:creator => current_user, :editor => current_user})

  if @comment.save
    success message here
    redirect_to url_for(@commentable)
  else
    failure message here
    render :controller => @commentable.class.downcase.pluralize, :action => :show
  end
end

  protected
    def find_commentable
      params.each do |name, value|
        if name =~ /(.+)_id$/
          return $1.classify.constantize.find(value)
        end
      end
      nil
    end
查看部分注释和表单(使用Haml):

我似乎知道如何处理验证错误。当触发验证错误时,它似乎不会触发f.error\u消息。此外,当触发render时,它会将用户带到具有以下url的页面:a/2/comments,当我希望它呈现a/2时

最新解决方案:

def create
  subject = ""
  if !@comment.save
    subject = "?subject=#{@comment.subject}"
  end
  redirect_to @back + subject
end
然后在A控制器中显示操作:

if params.has_key?('subject')
  @comment = Comment.create(:subject => params[:subject])
else
  @comment = Comment.new
end

这是可行的,但感觉有点难看…

因为你不知道你将在评论控制器中接收到什么样的对象,所以很难将你的头绕在它周围

当它不是多态关系时,它要简单得多。在我们了解如何做到这一点之前,我们需要了解实现单一版本的最佳方法

我应该注意的是,这假设您的资源/路线定义正确:

map.resources:posts,:has_many=>[:comments] map.resources:pages,:has_many=>[:comments]

假设我们有一个简单的例子,一篇文章有很多评论。下面是一个示例方法:

class CommentsController < ApplicationController
  before_filter => :fetch_post 

  def create
    @comment = @post.comments.new(params[:comment])

    if @comment.save
      success_message_here
      redirect post_path(@post)
    else
      error_message_here
      redirect_to post_path(@post)
    end
  end

  protected
    def fetch_post
      @post = Post.find(params[:post_id])
    end
end
这将使您的表单变得简单:


非常好的解决方案。出于好奇,为什么不直接在表单中包含创建者和编辑id?在我看来,这是一种降低控制器复杂性的简单方法。话虽如此,视图是否应该比控制器更干净?LDK的一般规则是,您不应该信任用户输入。即使使用隐藏字段,恶意用户也可以将他们想要的任何ID注入表单中,然后将其传递,从而模拟其他用户。通过删除该选项,您将使应用程序更加安全。
before_filter :fetch_post

    def show
      @comment = @commentable.comments.build
    end

    protected
      def fetch_post
        @post = @commentable = Post.find(params[:id])
      end
<% form_for [ @commentable, @comment ] do |f| %>
  #Your form fields here (DO NOT include commentable_type and or commentable_id also don't include editor and creator id's here either. They will created in the controller.)
<% end %>
def create
  @commentable = find_commentable
  # Not sure what the relationship between the base parent and the creator and editor are so I'm going to merge in params in a hacky way
  @comment = @commentable.comments.build(params[:comment]).merge({:creator => current_user, :editor => current_user})

  if @comment.save
    success message here
    redirect_to url_for(@commentable)
  else
    failure message here
    render :controller => @commentable.class.downcase.pluralize, :action => :show
  end
end

  protected
    def find_commentable
      params.each do |name, value|
        if name =~ /(.+)_id$/
          return $1.classify.constantize.find(value)
        end
      end
      nil
    end