Ruby 在 Rails 上:在共享文件夹上呈现表单

Ruby on Rails: render form on a shared folder

我想将表单放在共享文件夹中,以便 DRY 代码并为 [:admin, :posts] 和 :posts 呈现此表单。 所以我创建了一个文件夹并将表格放在 app/views/shared/_form.html.slim

- if params[:admin][:posts]
  post = [:admin, @post]
- if params[:posts]
  post = @post

= simple_form_for(post, :html => { :multipart => true }) do |f|
   = f.association :categories, label: "Select the Categories:", as: :check_boxes , collection: @categories.map{|c| [c.name, c.id]}, include_hidden: false
   = f.input :title
   = f.input :subtitle
   - if @post.attachment.present?
     .attachment
       p
         = image_tag(@post.attachment.thumb.url, alt: 'Image', class: "img-responsive img-thumbnail")
         = f.check_box :remove_attachment
         | Remove image
         br
          .text-center
            small
              sample
                = "File_size #{number_to_human_size(@post.attachment.size)}"
   = f.input :attachment, as: :file, label: "File"
   = f.input :attachment_cache, as: :hidden
   = f.input :remote_attachment_url, label: "Enter URL to an image"
   = f.input :content, size: "150x150"

   = f.button :submit, class: 'btn-primary'

然后

app/views/admin/post/new.html.slimapp/views/posts/edit.html.slim

我添加了渲染:

== render 'shared/form', post: @post

所以我尝试 运行 但我遇到了这个错误:

ActionView::Template::Error (undefined method `[]' for nil:NilClass):
    1: - if params[:admin][:posts]
    2:   post = [:admin, @post]
    3: - if params[:posts]
    4:   post = @post

这只是我的一个想法。在这种情况下可以这样做还是忘记这样做?

路线:

rake routes | grep post
Running via Spring preloader in process 2187
             admin_posts POST   /admin/posts(.:format)                   admin/posts#create
          new_admin_post GET    /admin/posts/new(.:format)               admin/posts#new
              admin_post DELETE /admin/posts/:id(.:format)               admin/posts#destroy
nullify_posts_admin_user PATCH  /admin/users/:id/nullify_posts(.:format) admin/users#nullify_posts
                    root GET    /                                        posts#index
         published_posts GET    /posts/published(.:format)               posts#published
             draft_posts GET    /posts/draft(.:format)                   posts#draft
            recent_posts GET    /posts/recent(.:format)                  posts#recent
            publish_post PATCH  /posts/:id/publish(.:format)             posts#publish
          unpublish_post PATCH  /posts/:id/unpublish(.:format)           posts#unpublish
                   posts GET    /posts(.:format)                         posts#index
               edit_post GET    /posts/:id/edit(.:format)                posts#edit
                    post GET    /posts/:id(.:format)                     posts#show
                         PATCH  /posts/:id(.:format)                     posts#update
                         PUT    /posts/:id(.:format)                     posts#update

我看到你想做的是弄清楚你是在管理部分还是标准 post 部分,然后以这种方式更改表单的 url。

这是一种 non-standard 的做法。 一般来说,我所看到的是只有表单的主体在共享表单部分,但是动作保存在外部部分所以例如:

app/views/admin/post/new.html.slim:

= simple_form_for(post, :html => { :multipart => true }) do |f|
  == render 'shared/post_form', f: f, post: post

app/views/shared/_post_form.html.slim:

   = f.association :categories, label: "Select the Categories:", as: :check_boxes , collection: @categories.map{|c| [c.name, c.id]}, include_hidden: false
   = f.input :title
   = f.input :subtitle
   - if post.attachment.present?
     .attachment
       p
         = image_tag(post.attachment.thumb.url, alt: 'Image', class: "img-responsive img-thumbnail")
         = f.check_box :remove_attachment
         | Remove image
         br
          .text-center
            small
              sample
                = "File_size #{number_to_human_size(post.attachment.size)}"
   = f.input :attachment, as: :file, label: "File"
   = f.input :attachment_cache, as: :hidden
   = f.input :remote_attachment_url, label: "Enter URL to an image"
   = f.input :content, size: "150x150"

   = f.button :submit, class: 'btn-primary'

注意:如果将 post 作为局部变量传递给表单,则应将其与 post 一起使用,而不是 @post(因为 @post 完全忽略局部变量您传入的变量并返回到来自控制器的任何内容,在这种情况下,为什么还要麻烦传入局部变量?) 您也可能永远不要在模板中调用另一个变量 post ...因为它会覆盖旧的 post 变量然后消失。将其命名为不同的名称,例如,在这种情况下,如果您真的想像以前一样使用模板,您可以将其命名为 post_url_params

所以按照@Taryn East 的想法,我把这个和工作的:

app/views/admin/posts/new.html.slim

= title("New Post")
.header
  h1 New Post

== render 'form', post: @post

app/views/admin/posts/edit.html.slim

= title("Edit Post", @post.title)

.header
  h1 Edit Post

== render "form", post: @post

app/views/admin/posts/_form.html.slim

= simple_form_for([:admin, post], :html => { :multipart => true }) do |f|
  == render "shared/post_form", f: f, post: post

app/views/posts/_form.html.slim

= simple_form_for(post, :html => { :multipart => true }) do |f|
  == render "shared/post_form", f: f, post: post

app/shared/_post_form.html.slim

= f.association :categories, label: "Select the Categories:", as: :check_boxes , collection: @categories.map{|c| [c.name, c.id]}, include_hidden: false
= f.input :title
= f.input :subtitle
- if post.attachment.present?
  .attachment
    p
      = image_tag(post.attachment.thumb.url, alt: 'Image', class: "img-responsive img-thumbnail")
      = f.check_box :remove_attachment
      | Remove image
      br
       .text-center
         small
           sample
             = "File_size #{number_to_human_size(post.attachment.size)}"
= f.input :attachment, as: :file, label: "File"
= f.input :attachment_cache, as: :hidden
= f.input :remote_attachment_url, label: "Enter URL to an image"
= f.input :content, input_html: { rows: '15' }

= f.button :submit, class: 'btn-primary'