【问题标题】:rails ajax overwriting all partials when refreshing page刷新页面时rails ajax覆盖所有部分
【发布时间】:2016-12-01 08:44:38
【问题描述】:

我正在对 Rails 中的简单 ajax 示例进行简单变体:http://guides.rubyonrails.org/working_with_javascript_in_rails.html#a-simple-example

我正在尝试创建一个用户显示视图,在该视图中按下按钮会创建新帖子。这些帖子都列在同一显示页面上的用户下方,并在创建时出现。

帖子创建良好并在页面上正确显示,但是当我刷新页面时,我的

  @post = User.posts.build() 

覆盖所有以前创建的帖子,给每个帖子一个 nul id。 另外,将 create.js.erb 放在 views 文件夹中是否正确,还是应该放在 assets/javascripts 文件夹中?

这是我的文件:

用户控制器

def show
    @user = User.find(params[:id])
    @posts = Post.all
    @post = @user.posts.build
end

用户/show.html.erb

<%= "user-id: #{@user.id}" %>

<ul id="posts">
<%= render :partial => @posts %>
</ul>


<%= form_for(@post, remote: true) do |f| %>
  <%= f.hidden_field :user_id, :value => @user.id %>
  <%= f.submit %>
<% end %>

PostsController

def create
  puts params[:post][:user_id]
  @user = User.find(params[:post][:user_id])
  puts @user
  @post = @user.posts.build()
  respond_to do |format|
    if @post.save
      format.html { redirect_to @post, notice: 'Post was successfully created.' }
      format.js   {}
      format.json { render json: @post, status: :created, location: @post }
    else
      format.html { render action: "new" }
      format.json { render json: @post.errors, status: :unprocessable_entity }
    end
    Rails.logger.info(@post.errors.inspect) 
  end
end

def index
    @posts = Post.all
    @post = Post.new
end

posts/_post.html.erb

 <li><%= @post.id %></li>

posts/create.js.erb

 $("<%= escape_javascript(render @post) %>").appendTo("#posts");

【问题讨论】:

    标签: javascript ruby-on-rails ajax


    【解决方案1】:

    问题

    您的局部变量呈现所有新帖子的原因是因为您在局部变量中使用 实例变量 @post 而不是 局部变量 post

    在您的UsersController#show 操作中,您设置了@post = @user.posts.build。当您在部分中渲染&lt;%= @post.id %&gt; 时,您正在引用来自控制器并设置为新帖子的同一个变量。

    似乎之前创建的所有帖子都被“清空”了,但实际上只是您不断地呈现新帖子,而不是现有帖子。

    解决方案

    您需要更新您的局部变量以使用 局部变量,而不是 实例变量

    <li><%= post.id %></li>
    

    当您呈现这样的记录集合时,Rails 会自动提供此局部变量

    <%= render @user.posts %>
    

    或者

    <%= render partial: "posts/post", collection: @user.posts %>
    

    以后如何避免

    这是一个非常常见的错误,很容易被忽略。

    因此,我的建议是stop using instance variables in partials

    资源

    【讨论】:

    • 非常感谢您的回答,我会制定一个规则,以避免部分实例变量
    【解决方案2】:

    通过避免使用 _post 部分来显示较旧的帖子找到了解决方法:

    编辑:users/show.html.erb

    <ul id="posts">
      <% @posts.each do |post| %>
        <li>
          <%= post.id %>
        </li>
      <% end %>
    </ul>
    

    我认为这不是一个理想的解决方案,但现在可以正常工作。

    【讨论】:

      【解决方案3】:

      是的,你是对的。

      create.js.erb 后缀为erb 以帮助您向其添加代码 ruby​​。

      在此文件中编写代码与在视图 html.erb 上编写 JavaScript 代码的语法相同

      <script>
        $("<%= escape_javascript(render @post) %>").appendTo("#posts");
      </script>
      

      【讨论】:

      • 感谢回复,你明白为什么我的帖子列表刷新页面后都变成Post.new了吗?
      • 在 posts_controller/index 上 @post = Post.new 是什么意思?
      • 我已将其删除,因为这是一个错误,但用户显示视图仍将每个帖子显示为 Post.new 而不是单独的帖子
      • 我认为您应该将文件posts/_post.html.erbposts/create.js.erb 移动到文件夹views/users
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-23
      • 1970-01-01
      • 1970-01-01
      • 2012-02-25
      相关资源
      最近更新 更多