使用Rails 4,制作一个简单的单页应用程序。
我的root设置为索引页面,我在其中显示了一系列非常短的帖子。另一方面,我有一个部分表格,所以有人可以轻松提交新帖子。
我决定对表单提交进行Ajax化,以便将新帖子附加到列表顶部而不重新加载页面并清除表单。
关于我的表单的一个注释 - 每个帖子都属于一个公司,所以我在表单中有<%= fields_for Company.new do |company|... %>
。在创建操作中,我在公司上调用first_or_create
,因此如果公司不存在,则会在提交时创建并与新帖相关。
最终,我必须在我的表单中显式创建新对象,而不是将本地传递给我的部分并使用表单中的裸字。我试图理解为什么会这样,以及如何最终实现更加接受的方法。
在下面实现我的终极解决方案之前,我试图让它像这样工作:在posts控制器中的我的索引操作中,不仅声明@post = Post.new
和@company = Company.new
而且声明{{1 }和@new_company = Company.new
。然后在我的create.js.erb文件中,重新呈现表单时,将@new_post = Post.new
和@new_company
作为@new_form
等本地人传递,然后在表单中,使用简单的单词{{1 }}。这似乎是更标准的方式,但在我放弃实例变量和本地并且只是在表单中显式创建新对象之前,我无法使其工作。
posts_controller.rb:
$(".js-ref-form").html("<%= escape_javascript(render partial: 'form', locals: { post: @new_post, company: @new_company ) %>");
视图/帖/ create.js.erb:
<%= form_for post .... %>
视图/帖/ _form.html.erb
class PostsController < ApplicationController
respond_to :html, :js
def index
@company = Company.new
@post = Post.new
@posts = Post.all
end
def create
@company = Company.where(name: post_params[:company]).first_or_create
@post = @company.posts.build(company_id: @company.id, details: post_params[:details], link: post_params[:link],
expiration: post_params[:expiration], code: post_params[:code], limit: post_params[:limit])
if @post.save
flash[:success] = "Post submitted!"
else
flash[:danger] = "Problem submitting post. Please try again."
end
respond_with(@post) do |f|
f.html { redirect_to root_path }
end
end
视图/帖/ index.html.erb:
<% if @post.valid? %>
$(".js-post").prepend("<%= escape_javascript(render(@post)) %>");
$(".js-post-form").html("<%= escape_javascript(render partial: 'form') %>");
<% else %>
$(".js-post-form").replaceWith("<%= escape_javascript(render partial: 'form') %>");
<% end %>
的routes.rb
# writing form_for @post doesn't work with this solution, and if I pass
# in locals to the partials, i.e. render partial: 'form', locals: { post: @post }
# and using form_for post didn't work either
<%= form_for Post.new, html: { class: 'form-horizontal' }, remote: true do |f| %>
<h2>Add Post</h2>
<%= render 'shared/error_messages' %>
<%= f.label :company, "Company" %>
# Same problem as the comment above
<%= fields_for Company.new do |company| %>
<%= f.text_field :company, class: 'form-control' %>
<% end %>
<br>
<%= f.label :details, "What's new?" %> <span class="detail-counter pull-right"></span>
<%= f.text_area :details, class: 'form-control' %>
<br>
<%= f.submit "Submit", class: 'btn btn-lg btn-block btn-primary' %>
<% end %>
<script type="text/javascript">
var elem = $(".detail-counter");
$("#post_details").limiter(140, elem);
</script>
模型:
post.rb
<div class="row">
<div class="col-md-4 post-form">
<div class="js-post-form">
<%= render partial: 'form' %>
</div>
</div>
<div class="col-md-8">
<div class="post-list js-posts">
<% if @posts.any? %>
<%= render @posts %>
<% else %>
No posts yet!
<% end %>
</div>
</div>
</div>
company.rb
CompanyPosts::Application.routes.draw do
resources :posts
root to: 'posts#index'
end
答案 0 :(得分:1)
好的,想通了。为了能够将局部传递给我的表单部分并在表单中使用单词,我必须为{em> new 帖子和 new 公司对象创建实例变量{ {1}}动作,而不是我以前做的索引动作。
然后在我的index.html.erb文件中,我可以执行posts#create
并在create.js.erb中执行:
<%= render partial: 'form', locals: { post: @post, company: @company } %>
另外,我必须在posts控制器中定义两个参数,因为我实际上是在同时提交两个表单。我修改了<% if @post.valid? %>
$(".js-posts").prepend("<%= escape_javascript(render(@post)) %>");
$(".js-post-form").html("<%= escape_javascript(render partial: 'form', locals: { post: @new_post, company: @new_company }) %>");
<% else %>
$(".js-post-form").html("<%= escape_javascript(render partial: 'form', locals: { post: @post, company: @company }) %>");
<% end %>
标记,以我希望更合适的方式工作:
fields_for
现在我不必在表单中显式创建对象。虽然任何进一步的改进建议仍然受到赞赏。