Reputation: 2380
I have a rails app with a real time chat (1v1). I'd like to implement a file upload function via AJAX where on submitting the file upload form the filename will show up in the chat without full page reload.
I'm trying to use remotipart gem to be able to submit the refile file upload form via AJAX. Files are uploaded directly to S3 so those never hit my app at all (I don't need to display them), I just send the filename/URL via the chat to the other user.
On the top of these uploading starts when I choose the file thanks to refile gem. So when I submit('send file' button) the form it just saves the file attributes(message.message_attachment/id,url,size, etc.) and message_id into the db.
On the pic you can see what I wanna implement. There is a separate form for chat input text (message.body) and an other form for file uploading (message.message_attachment). So far chat is working perfectly with private_pub gem. Choosing file happens properly as well (including uploading the file to S3 and 204 status response) but submitting the form (saving the message to db by clicking on 'send file') only works with full page reload.
The solutions I tried:
For the chat messaging I use the same create.js.erb but I don't have to use respond_to js thanks to the private_pub gem. I just have to subscribe and publish to/with the conversation_path(@path).
I feel I'm pretty close to the solution since it works with full page reload. I don't know if the compatibility between private_pub solution (no need for respond_to js) and remotipart w/ refile (respond_to js needed) can cause the problem.
message model:
create_table "messages", force: :cascade do |t|
t.text "body"
t.integer "conversation_id"
t.integer "user_id"
t.string "message_attachment"
t.string "message_attachment_id"
t.string "message_attachment_filename"
t.integer "message_attachment_size"
t.string "message_attachment_content_type"
......
end
create.js.erb
<% publish_to @path do %>
var id = "<%= @conversation.id %>";
var chatbox = $(".chatboxcontent");
chatbox.append("<%= j render(partial: @message ) %>");
chatbox.scrollTop(chatbox[0].scrollHeight);
$(".chatboxtextarea").val("");
var filechosen = $('.choosefile').val();
if (filechosen != "") {
$(".refile_form").find("input[type=submit]").hide();
$('.choosefile').val("");
$('#progresspercent').hide();
}
<% end %>
message/_show.html.erb
<div class="chatboxcontent">
<% if @messages.any? %>
<%= render @messages %>
<% end %>
</div>
<div class="chatboxinput">
<%= form_for([@conversation, @message], :remote => true, :html => {id: "conversation_form_#{@conversation.id}"}) do |f| %>
<%= f.text_area :body, class: "chatboxtextarea", "data-cid" => @conversation.id %>
<% end %>
<%= form_for([@conversation, @message], html: {class: "refile_form"}, remote: true, authenticity_token: true) do |form| %>
<span class="btn btn-success btn-sm btn-file">Choose file
<%= form.attachment_field :message_attachment, direct: true, presigned: true, class: "choosefile" %></span>
<%= form.submit "Send File", class: "btn btn-primary btn-sm btn-submit-refile" %>
<% end %>
</div>
<%= subscribe_to conversation_path(@conversation) %>
messages controller for chat before implementing file uploading:
def create
@conversation = Conversation.find(params[:conversation_id])
@message = @conversation.messages.build(message_params)
@message.user_id = current_user.id
@message.save!
@path = conversation_path(@conversation)
end
messages controller that works fine w/ full page reload for uploading:
def create
@conversation = Conversation.find(params[:conversation_id])
@message = @conversation.messages.build(message_params)
@message.user_id = current_user.id
@message.save!
@path = conversation_path(@conversation)
if @message.message_attachment_id
respond_to do |format|
format.html { redirect_to :back }
# I've tried w/ and with no format.js as well.
#format.js { render: 'create.js.erb }
end
end
end
UPDATE:
Problem solved: Typo in the app.js //=require jquery.remotipart...... - respond_to js is not necessary thanks to private_pub gem - authencity_token: true for form helper also not necessary thanks to remotipart gem - remotipart needed to be able to submit file form via AJAX
Upvotes: 1
Views: 735