2

假设我有一个 Rails 应用程序,用户可以在其中写博客文章。用户开始输入后,将调用一个 AJAX 函数,该函数提交一个 POST 请求并保存博客文章。我想做的是能够检查博客文章是否已经在数据库中,然后在用户键入时通过 AJAX 不断地保存它。

我正在为标题和内容博客文章输入区域使用 HTML5 contenteditable 属性:

<div id="entry-create-partial">
    <div id="title-create-partial" name="title" contenteditable="true" data-placeholder='Title it' style="color:black"></div>
    <div id="content-create-partial" name="content" contenteditable="true" data-placeholder='Write anything' style="color:gray"></div>
</div>

这是执行我想要的JavaScript:

$(function(){
        if ($("#title-create-partial").length > 0) {
            setTimeout(autoSavePost, 6000);
        }
    });

    function autoSavePost(){
        $.ajax({
            type: "POST",
            url: "/submissions",
            dataType: "json",
            data: {title: $("#title-create-partial").text().serialize(), content: $("#content-create-partial").text().serialize()},
            success: function(){
                $("#success-indicate").fadeIn().delay(4000).fadeOut();
            }
        });
        setTimeout(autoSavePost, 6000);
    }

但是,在我的 JS 控制台中,我收到一条错误消息,指出我提供给 .ajax 的数据没有序列化方法。我不确定如何正确地将它传递给 AJAX。

此外,一旦我通过 AJAX 发送它,我不确定如何:content在数据库端更新它。这是createAJAX url 路由到的控制器:

    def create 
    @submission = Submission.where(title: params[:title]).first_or_create(
        title: params[:title],
        content: params[:content],
        user_id: params[:user_id]
        )
    @submission.user = current_user
    if @submission.save 
        redirect_to :action => :show, :id => @submission.id
    else
        redirect_to :action => :index
    end

end

如何从 contenteditable div 发送文本,然后在控制器中如何更新内容?我听说过 update_attributes,但我不确定如何使用它。

4

3 回答 3

3

这段代码在这里:

$("#title-create-partial").text()

返回一个字符串。然后你在一个字符串上调用一个名为 serialize() 的方法。没有名为 serialize() 的 JavaScript 方法。jQuery 有一个名为 serialize() 的方法,但它必须在 jQuery 对象上调用。字符串不是 jQuery 对象。据我所知, serialize() 甚至不适用于非表单元素。以下是您将如何使用序列化:

var str = $( "form" ).serialize();

或者,

var str = $( "#my_text_input, #my_select").serialize()

这将产生一个这样的字符串:

"text_input_name=hello&select_name=goodbye"

但是,根据 jQuery 文档,jQuery 会自动序列化您为 .ajax() 中的数据指定的键/值对——因此您不想再次序列化它们。

如何从 contenteditable div 发送文本,然后在控制器中如何更新内容?

您需要选择一个事件来触发您的 ajax 调用。最好的选择可能是设置一个超时时间,每 5 分钟关闭一次,这会调用您的 ajax 函数。

至于更新数据库中的内容,您可以查询您的数据库并查看用户是否有相同标题的帖子。如果查询返回 0 个结果,则使用该内容创建一个新帖子。否则,将帖子的内容设置为新内容。像这样的东西:

id = params[:session][:id] 
ajax_title = params[:title]
ajax_content = params[:content]

user = User.find id
posts = user.posts.where(title: ajax_title)

if posts.empty?
  post = user.posts.create(title: ajax_title, content: ajax_content)
else
  post[0].content = ajax_content
  post[0].save
end

假设您已经完成:

class User < ActiveRecord::Base
  has_many :posts
end

class Post < ActiveRecord::Base
  belongs_to :user
end
于 2013-08-21T04:40:03.393 回答
1

这与其说是答案,不如说是评论。因为有点长,所以写在这里。

我很难理解你的逻辑。似乎服务器会在每次点击时创建大量帖子。

假设您要写一篇题为“通过 AJAX 更新 Rails 模型”的帖子。

当您在标题输入中键入“U”时,会触发 Ajax,服务器收到一个标题“U”。db中没有标题为“U”的此类帖子,因此控制器创建了一个。

然后你输入“p”。同样没有这样的帖子,因此创建了新帖子“Up”。

现在你有两个帖子,“U”和“Up”。键入后将创建更多内容。

看到问题了吗?如果错了请纠正我。

添加:关于解决方案

我以前没有做过这样的案例,所以不能提供实践,只能提供一些想法。

主观上我认为通过直接打字创建帖子不是一个好主意,原因如上所述。我会建议:

  1. 基本:在提交时创建帖子,无论是正常请求的 Ajax。

  2. 高级:添加选项以另存为草稿。并添加功能以查看或从草稿加载(编辑表单)。该帖子与普通帖子相同,额外列“草稿”为真

  3. 甚至更高级:在输入大量代码后,在正文中说 100 个字符,将其自动保存为草稿。这类似于您的代码,主要区别在于服务器端草稿设置。

您可能还注意到,在 Stackoverflow 中,如果您写了答案但不提交,下次您返回时,答案草稿仍在表单中。这比您的情况更容易,因为答案始终与问题相关联,并且您只能逐个发布答案,因此可以轻松识别草稿。

但博文不同,它是主模型,没有关联,可以同时创建多个草稿。所以你需要注意吃水装载。

只是几分钱。

于 2013-08-21T05:30:23.843 回答
0

请仅text()在获取值标题和内容时使用。并且当使用serialize()从表单输入中获取数据时更有效。所以把你的代码改成下面。

$(function(){
        if ($("#title-create-partial").length > 0) {
            setTimeout(autoSavePost, 6000);
        }
    });

function autoSavePost(){
    $.ajax({
        type: "POST",
        url: "/submissions",
        dataType: "json",
        data: {title: $("#title-create-partial").text();, content: $("#content-create-partial").text();},
        success: function(){
            $("#success-indicate").fadeIn().delay(4000).fadeOut();
        }
    });
    setTimeout(autoSavePost, 6000);
}
于 2013-08-21T04:58:28.560 回答