gpt4 book ai didi

javascript - Rails 4 更新实例变量而无需重新加载页面

转载 作者:行者123 更新时间:2023-12-02 14:24:15 25 4
gpt4 key购买 nike

有没有办法可以在 View 中重新加载实例变量而不重新加载页面?

我有一个 AJAX 帖子,它创建了一个新记录。我希望将该记录添加到现有实例变量中。

所以我有一个诸如 action 之类的操作,它处理我在 action.html.erb 中的 View :

def action
@variable = Variable.where().to_a
end

然后我有一个执行操作的 AJAX 请求,例如 action2:

def action2
@new_record = Variable.create(params)
respond_to do |format|
format.html
format.json {render :json => @new_record.to_json}
end
end

有没有办法刷新 @variable 实例变量以包含新创建的记录?

我可以向 action 发出另一个 AJAX 请求吗?如果是这样,我如何在 action 中检测 AJAX 请求?

我已经用 request.xhr? 尝试过这个^^,但在我执行 JS .click() 后,它抛出了一个奇怪的 StandardError >?

我不确定我是否朝着正确的方向前进,但如果是的话,这里是我整理的所有代码......

我正在构建一个即时消息服务,我承认我完全是在拼凑一个原型(prototype)。我知道有更干净的方法可以处理高流量负载,但我现在正在开发一个原型(prototype)。

View 代码看起来像这样...有:HTML 聊天框,我每 2 秒发出一个 AJAX 请求来查找新消息,在同一个函数中,我向我所谓的 action< 发出 AJAX 请求 上面(实际上命名不同),在“刷新”函数之后,我有一个 .click() 函数来更新用户 View (刚刚提交的 View )。

<div id="wrapper">
<div id="menu">
<p class="welcome">Welcome, <b></b></p>
<p class="logout"><a id="exit" href="#">Exit Chat</a></p>
<div style="clear:both"></div>
</div>

<div id="chatbox">
<% @messages.each do |message| %>
<% if session[:email] == message.email %>
<!-- post to the right side -->
<div id="right-side">
<p>Email: <%= message.email %></p>
<p>Message: <%= message.message %></p>
</div>
<% else %>
<!-- post to the left side -->
<div id="left-side">
<p>Email: <%= message.email %></p>
<p>Message: <%= message.message %></p>
</div>
<% end %>
<% end %>
</div>

<form id="frm1" action="">
Message: <input id="message_input" type="text" name="fname"><br>
<!-- <input type="submit" value="Submit"> -->
<button name="submitmsg" type="submit" id="submitmsg">Try it</button>
</form>
</div>

<p id="demo"></p>
<script>

function retrieveMessages(){
var message;
$.ajax({
type:"GET",
url:"<%= get_messages_path %>",
dataType:"json",
data: {chat_id: <%= @message_info[:chat_id] %>,
last_message: <%= @messages.last.created_at.to_i %>},
success:function(data){
if (data != null){
console.log(data);
console.log(data.message);
message = data.message;
document.getElementById("chatbox").innerHTML += message + '<br>';
}
}
});

$.ajax({
type:"GET",
url:"<%= new_message_path %>",
dataType:"json",
success:function(data){
console.log("success!");
}
}
});
setTimeout(retrieveMessages, 2000);
}

$(document).ready(function(){
//get messages
setTimeout(retrieveMessages, 2000);

//send messages
$("#submitmsg").on('click', function(e){
e.preventDefault();
var x = document.getElementById("frm1"); //This is the form, and not the value of the textbox
var text = "";
var i;
for (i = 0; i < x.length ;i++) {
text += x.elements[i].value;
}
// document.getElementById("chatbox").innerHTML += text;
text_with_br = text + "<br>"
document.getElementById("chatbox").innerHTML += text_with_br;
document.getElementById("frm1").reset();
// console.log(document.getElementById("right"));
//Actual message is in 'text'
$.ajax({
url: "/messages",
method: "post",
data: { message: text,
chat_id: <%= @message_info[:chat_id] %>,
message_counter: <%= @message_info[:message_counter] + 1 %> },
dataType: "JSON",
success: function(response){
//do something,maybe notify user successfully posted their message
},
error: function(error){
console.log(error);
}
});

});
});
</script>

然后对于我拥有的 action 操作(实际上是 new 操作,我所说的 @variable 实际上是 @messages :

def new
# debugger
# Message.create(:chat_id => 5)
if session[:email].nil?
#user not logged in
redirect_to new_session_path(:message => "need to login")
else
@user = User.where(:email => session[:email]).first
@message_info = Hash(email: @user.email, message_counter: 0, chat_id: Message.last.chat_id + 1)
@messages = Message.where(:chat_id => @message_info[:chat_id]).to_a

respond_to do |format|
format.html
format.json
end

end
end

然后执行AJAX请求以获取最新消息(以便其他浏览器的查看者可以查看)的操作如下...

def get
@new_message = Message.where(["created_at > ?", Time.at(params[:last_message].to_i)]).first

respond_to do |format|
format.html
# format.json {render json: @new_message}
format.json {render :json => @new_message.to_json}
end
end

更新

@eggroll 建议使用下面的代码,但我遇到了引导问题

enter image description here

最佳答案

从您的代码开始,下面是我尝试的解决方案。我重命名了元素,希望它能让这段代码更加 self 记录,从而让您更容易辨别我所做的事情。它并不完美,但它在 Chrome 中对我有用,所以希望它能有所帮助。我假设起始 chat_id 为 1。如果不是,您可以在 Controller 中的 get_last_chat_id 方法中调整它。

(注意:有几行代码对您来说是多余的,但对于我来说是必要的,以便能够在我现有的应用程序之一中运行此代码。您还应该知道我'我使用 Postgres、jQuery、Devise、HAML 和 Bootstrap 4 alpha。)

app/controllers/messages_controller.rb

class MessagesController < ApplicationController

before_action :authenticate_user!
before_action :set_current_user_email, only: [:index, :display_all_messages]
before_action :set_current_messages, only: [:display_all_messages]

def index
end


def get_last_chat_id
last_chat_id = Message.pluck(:chat_id).max
if last_chat_id
puts '*** LAST CHAT ID: ' + last_chat_id.to_s
else
last_chat_id = 0
puts '*** LAST CHAT ID: ' + last_chat_id.to_s
end

respond_to do |format|
format.json { render json: last_chat_id }
end
end


def save_new_message
new_message = Message.new do |msg|
msg.email = params[:email]
msg.message_text = params[:message_text]
msg.chat_id = params[:chat_id]
end

puts '*** NEW MESSAGE EMAIL: ' + new_message.email
puts '*** NEW MESSAGE TEXT: ' + new_message.message_text
puts '*** NEW MESSAGE CHAT ID: ' + new_message.chat_id.to_s

# Source: https://makandracards.com/housetrip-deck/16879-jquery-ajax-success-done-will-not-run-callbacks-if-request-is-json-but-the-response-is-empty-typical-200
respond_to do |format|
if new_message.save
puts '*** NEW MESSAGE WAS SAVED!!!'
format.json { render json: { ok: true }, status: :ok }
else
puts '*** NEW MESSAGE WAS NOT SAVED!!!'
format.json { render json: { ok: false }, status: :unprocessable_entity }
end
end
end


def display_all_messages
respond_to do |format|
if @current_messages
format.js { }
else
puts '*** THERE ARE NO MESSAGES TO DISPLAY!!!'
end
end
end


private

def set_current_messages
@current_messages = Message.by_created_desc
end


def set_current_user_email
@current_user_email = current_user.email
end


def message_params
params.require(:message).
permit(:email, :message_text)
end


end

app/models/message.rb

class Message < ActiveRecord::Base

scope :by_created_desc, -> { order(created_at: :desc) }

end

db/migrate/20160717000100_create_messages.rb

class CreateMessages < ActiveRecord::Migration
def change

create_table :messages do |t|

t.string :email, null: false
t.text :message_text
t.integer :chat_id, null: false

t.timestamps null: false

end

add_index :messages, :chat_id, unique: true

end
end

app/assets/javascripts/messages.js(2016-07-17更新)

var messagesRefresher;

$(document).ready(function(){

// AJAX error handling, outputting error messaging to the console
$(document).ajaxError(function (event, jqxhr, settings, thrownError) {
console.log('EVENT: ' + JSON.stringify(event, null, '\t'));
console.log('JQXHR: ' + JSON.stringify(jqxhr));
console.log('SETTINGS: ' + JSON.stringify(settings, null, '\t'));
console.log('THROWN ERROR: ' + thrownError);
});

messagesRefresher = setInterval(refreshMessages, 2000);

$('#new-message-create-btn').on('click', function(e){
e.preventDefault();
$('#new-message-create-btn').addClass('no-display');
$('#new-message-form-wrapper').removeClass('no-display');
});

$('#new-message-cancel-btn').on('click', function(e){
e.preventDefault();
$('#new-message-form-wrapper').addClass('no-display');
$('#new-message-create-btn').removeClass('no-display');
});

$('#new-message-submit-btn').on('click', function(e){
e.preventDefault();
var newMessageEmail = $('#new-message-email').val();
var newMessageText = $('#new-message-text').val();

console.log('*** NEW MESSAGE EMAIL: ' + newMessageEmail);
console.log('*** NEW MESSAGE TEXT:');
console.log(newMessageText);

getLastChatId('/messages/get_last_chat_id').done(function(lastChatId) {
var newMessageChatId = lastChatId + 1;
console.log('*** NEW MESSAGE CHAT ID: ' + newMessageChatId)

saveNewMessage('/messages/save_new_message?email=' + newMessageEmail + '&message_text=' + newMessageText + '&chat_id=' + newMessageChatId).done(function(data) {

console.log('*** MESSAGE # ' + newMessageChatId + ' SAVED!!!')

$('#new-message-form-wrapper').addClass('no-display');
document.getElementById('new-message-form').reset();
$('#new-message-create-btn').removeClass('no-display');

refreshMessages;
});

});

});

});


function refreshMessages() {
displayAllMessages('/messages/display_all_messages').done(function(data) {
console.log('*** MESSAGES REFRESHED!!!');
});
};


function getLastChatId(url) {
return $.ajax({
url: url,
type: 'get',
dataType: 'json'
})
.fail(function() {
alert('AJAX Get Last Chat Id Error');
});
};


function saveNewMessage(url) {
return $.ajax({
url: url,
type: 'get',
dataType: 'json'
})
.fail(function() {
alert('AJAX Save New Message Error');
});
};


function displayAllMessages(url) {
return $.ajax({
url: url,
type: 'get',
dataType: 'script'
})
.fail(function() {
alert('AJAX Display All Messages Error');
});
};


$(window).unload(
function(event) {
clearInterval(messagesRefresher);
}
);

app/views/layouts/application.html.haml(片段)(添加时间:2016-07-18)

.
.
.

%head

%meta{ charset: 'UTF-8' }
%meta{ name: 'viewport', content: 'width=device-width, initial-scale=1, shrink-to-fit=no' }

-# Derived from: http://v4-alpha.getbootstrap.com/getting-started/browsers-devices/
%meta{ 'http-equiv' => 'X-UA-Compatible', content: 'IE=edge' }

= csrf_meta_tags

-# For page-specific meta tags
= content_for?(:meta_tag) ? yield(:meta_tag) : ""

%title Chatbox

= stylesheet_link_tag 'application'
= yield :page_stylesheet_link_tags

= javascript_include_tag 'application'
= yield :page_specific_javascript

.
.
.

app/views/messages/index.html.haml

- content_for :page_specific_javascript do
= javascript_include_tag 'messages.js'

#chatbox
%h1 Chatbox

= link_to 'New Message', 'javascript:;', id: 'new-message-create-btn', class: 'btn btn-sm btn-primary'

#new-message-form-wrapper.no-display
= form_tag messages_path, id: 'new-message-form' do
= hidden_field_tag 'new-message-email', @current_user_email
#new-message-form-label-wrapper
= label_tag 'new-message-text', 'Enter Your Message:'
#new-message-form-text-wrapper
= text_area_tag 'new-message-text', nil, rows: 6, cols: 70
#new-message-form-buttons-wrapper
= submit_tag 'Post Message', id: 'new-message-submit-btn', class: 'btn btn-sm btn-success'
= link_to 'Cancel', 'javascript:;', id: 'new-message-cancel-btn', class: 'btn btn-sm btn-secondary'


#display-messages-wrapper

#messages-column-left.pull-md-left
%h3 Messages From Others
#messages-other-users

#messages-column-right.pull-md-right
%h3 My Messages
#messages-current-user

app/views/messages/display_all_messages.js.haml

$('#messages-other-users').html('');
$('#messages-current-user').html('');
- @current_messages.each do |msg|
- if msg.email == @current_user_email
$('#messages-current-user').append("#{ escape_javascript render(partial: 'message', locals: { email: msg.email, message_created_at: msg.created_at, message_text: msg.message_text }) }");
- else
$('#messages-other-users').append("#{ escape_javascript render(partial: 'message', locals: { email: msg.email, message_created_at: msg.created_at, message_text: msg.message_text }) }");

app/views/messages/_message.html.haml

.message-wrapper

.message-attribution-wrapper
%span.message-attribution-label Posted by:
%span.message-attribution-text=email + ' on ' + message_created_at.strftime('%Y-%m-%d') + ' at ' + message_created_at.strftime('%I:%M:%S %p')

.message-text-wrapper
.message-label Message:
.message-text= message_text

app/assets/stylesheets/messages.scss(2016-07-17更新)

.no-display {
display: none !important;
}

#chatbox {
width: 90%;
margin: .5em auto;
}

#new-message-form-wrapper {
width: 48%;
padding: 1em;
border: 1px solid #ccc;
}

#new-message-form-label-wrapper > label {
font-weight: 700;
}

#new-message-form-buttons-wrapper {
margin-top: .5em;
}

#new-message-submit-btn {
margin-right: .3em;
}

#new-message-submit-btn,
#new-message-cancel-btn {
width: 8em;
}

#new-messages-form-wrapper,
#display-messages-wrapper {
margin-top: 1.5em;
}

#messages-column-left,
#messages-column-right {
width: 48%;
}

.message-wrapper {
width: 96%;
margin: 1em auto;
padding: .5em;
border: 1px solid #ccc;
}

.message-attribution-label,
.message-label {
font-weight: 700;
}

config/routes.rb

Rails.application.routes.draw do

resources :messages, only: [:index]
get 'messages/get_last_chat_id', to: 'messages#get_last_chat_id'
get 'messages/save_new_message', to: 'messages#save_new_message'
get 'messages/display_all_messages', to: 'messages#display_all_messages'

end

assests/javascripts/application.js(添加时间:2016-07-18)

//= require jquery 
//= require jquery_ujs
//= require jquery-ui
//= require bootstrap-sprockets

config/initialization/assets/rb(添加时间:2016-07-18)

Rails.application.config.assets.precompile += %w( messages.js )

assets/stylesheets/application.scss(添加时间:2016-07-18)

@import 'bootstrap_4a/bs_4a_variable_overrides'; 
@import 'bootstrap';
@import 'bootstrap_4a/bs_4a_customization';

app/assets/stylesheets/bootstrap_4a/bs_4a_variable_overrides(添加时间:2016-07-18)

// http://v4-alpha.getbootstrap.com/getting-started/flexbox/
// Enabling flexbox means reduced browser and device support:
// Internet Explorer 9 and below do not support flexbox.
// Internet Explorer 10 has a few known quirks, requires using a prefix,
// and only supports the syntax from the old 2012 version of the spec.

$enable-flex: true;

app/assets/stylesheets/bootstrap_4a/bs_4a_customization(添加时间:2016-07-18)

// http://v4-alpha.getbootstrap.com/getting-started/browsers-devices/
// As of Safari v8.0, fixed-width .containers can cause Safari
// to use an unusually small font size when printing.
// One potential workaround for this is adding the following CSS:

@media print {
.container {
width: auto;
}
}

body {
position: relative;
}

Gemfile(添加时间:2016-07-18)

gem 'sass-rails', '~> 5.0' 
gem 'jquery-rails'
gem 'jquery-ui-rails', '~> 5.0.5'
gem 'autoprefixer-rails', '~> 6.3.6'
gem 'bootstrap', '~> 4.0.0.alpha3'

更新:apps/views/messages/display_all_messages.js.haml的 .js.erb 版本

$('#messages-other-users').html('');
$('#messages-current-user').html('');
<% @current_messages.each do |msg| %>
<% if msg.email == @current_user_email %>
$('#messages-current-user').append("<%= escape_javascript render(partial: 'message', locals: { email: msg.email, message_created_at: msg.created_at, message_text: msg.message_text }) %>");
<% else %>
$('#messages-other-users').append("<%= escape_javascript render(partial: 'message', locals: { email: msg.email, message_created_at: msg.created_at, message_text: msg.message_text }) %>");
<% end %>
<% end %>

关于javascript - Rails 4 更新实例变量而无需重新加载页面,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38413064/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com