b.herring
b.herring

Reputation: 643

using ajax on a form submit rails

Started POST "/users/3/tweets" for 127.0.0.1 at 2018-10-01 16:43:04 +0100
Processing by TweetsController#create as JS
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"a4GACc9npDT1aXdadefb62NbUVbAxA11JBQ/NDkCcPOS0l7wyBbJmwvdPdwZ8rZryT6LmxoFxI9wfv2RloLQIQ==", "tweet"=>{"content"=>"hello"}, "commit"=>"Create Tweet", "user_id"=>"3"}
  User Load (0.4ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2  [["id", 3], ["LIMIT", 1]]
  ↳ /Users/benherring/.rbenv/versions/2.4.4/lib/ruby/gems/2.4.0/gems/activerecord-5.2.1/lib/active_record/log_subscriber.rb:98
  User Load (0.2ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", 3], ["LIMIT", 1]]
  ↳ app/controllers/tweets_controller.rb:23
   (0.1ms)  BEGIN
  ↳ app/controllers/tweets_controller.rb:26
  Tweet Create (0.4ms)  INSERT INTO "tweets" ("content", "created_at", "updated_at", "user_id") VALUES ($1, $2, $3, $4) RETURNING "id"  [["content", "hello"], ["created_at", "2018-10-01 15:43:04.707047"], ["updated_at", "2018-10-01 15:43:04.707047"], ["user_id", 3]]
  ↳ app/controllers/tweets_controller.rb:26
   (1.7ms)  COMMIT
  ↳ app/controllers/tweets_controller.rb:26
  Rendering tweets/create.js.erb
  Rendered tweets/create.js.erb (7.3ms)
Completed 500 Internal Server Error in 34ms (ActiveRecord: 2.9ms)


  
ActionView::Template::Error (Missing partial tweets/_index with {:locale=>[:en], :formats=>[:js, :html], :variants=>[], :handlers=>[:raw, :erb, :html, :builder, :ruby, :jbuilder]}. Searched in:
  * "/Users/benherring/twitter-clone/app/views"
  * "/Users/benherring/.rbenv/versions/2.4.4/lib/ruby/gems/2.4.0/gems/devise-4.5.0/app/views"
):
    11: <% if @tweet.errors.any? %>
    12:   refreshForm('<%= j render "tweets/new", user: @user, tweet: @tweet %>');
    13: <% else %>
    14:   addTweet('<%= j render "tweets/index", tweet: @tweet %>');
    15:   refreshForm('<%= j render "tweet/new", user: @user, tweet: Tweet.new %>');
    16: <% end %>
  
app/views/tweets/create.js.erb:14:in `_app_views_tweets_create_js_erb__1236688757229574759_70092102807800'

im trying to submit a form so that the page doesnt reload, with ajax. the form does work without ajax at the moment, but i want it to be better. ive looked at the rails documentation and on here and i cant get my head around it. ive made changes to the form, controller and made a create.js.erb file but no luck. thanks

class TweetsController < ApplicationController
  before_action :authenticate_user!, :except => [:index]

   def index
    # @tweets = Tweet.all.order("created_at DESC")
    @tweets = Tweet.paginate(page: params[:page], per_page: 7).order('created_at DESC')

    @tweet = Tweet.new
    @user = current_user
  end

  def show
    @tweet = Tweet.find(params[:id])
  end

  def new
    # @tweet = Tweet.new
    # @user = current_user
  end

  def create
    # @user = current_user
    @user = User.find(params[:user_id])
    @tweet = Tweet.new(tweet_params)
    @tweet.user = @user
    if @tweet.save
         respond_to do |format|
        format.html { redirect_to user_tweets_path }
        format.js
      end
    else
      respond_to do |format|
        format.html { render 'tweets/index' }
        format.js
      end
    end
    # redirect_to user_tweets_path
  end


  def edit
    @tweet = Tweet.find(params[:id])
  end

  def update
    @tweet = Tweet.find(params[:id])
    @tweet.update(tweet_params)
    redirect_to tweets_path
  end

  def upvote
  @tweet = Tweet.find(params[:id])
  @tweet.upvote_by current_user
  # redirect_to :tweets
   if request.xhr?
    head :ok
  else
    redirect_to tweets_path
  end
end

def downvote
  @tweet = Tweet.find(params[:id])
  @tweet.downvote_by current_user
  redirect_to :tweets
end

  private
  def tweet_params
    params.require(:tweet).permit(:content)
  end
end

<%= simple_form_for [ @user ,@tweet], remote: true, id: "form-submit" do |f| %>
       <%= f.input :content, label: "Tweet" %>
       <%= f.button :submit, class: "btn btn-primary" %>
       <% end %>

function refreshForm(innerHTML) {
  const newTweetForm = document.getElementById('new_tweet');
  newTweetForm.innerHTML = innerHTML;
}

function addTweet(tweetHTML) {
  const tweets = document.getElementById('tweets');
  reviews.insertAdjacentHTML('beforeend', reviewHTML);
}

<% if @review.errors.any? %>
  refreshForm('<%= j render "tweets/new", user: @user, tweet: @tweet %>');
<% else %>
  addTweet('<%= j render "tweets/index", tweet: @tweet %>');
  refreshForm('<%= j render "tweet/new", user: @user, tweet: Tweet.new %>');
<% end %>

<h1 class="title text-primary">Home</h1>


<div class="tweet-form">
  <% if user_signed_in? %>
    <%= render 'new',user:@user, tweet:@tweet %>
  <% end %>
</div>
   <br>

<div id="tweets">
<% @tweets.each do |tweet|  %>
  <div class="card">
    <div class="card-description">
      <h4><%= link_to tweet.user.username, user_path(tweet.user) %></h4>
      <p class="tweet-content"><%= tweet.content %></p>
      <p><%= tweet.created_at.strftime("%B %d %Y, %l:%M%P") %></p>
      <%= link_to like_tweet_path(tweet),  method: :put do %>
      <p>Upvote <%= tweet.get_upvotes.size %>
      <% end %>
      <%= link_to dislike_tweet_path(tweet), method: :put do %>
      Downvote <%= tweet.get_downvotes.size %></p>
      <% end %>
    </div>
  </div>
<% end %>
</div>




<div class="pages">
  <%= will_paginate @tweets,renderer: BootstrapPagination::Rails %>
</div>

    config.action_view.embed_authenticity_token_in_remote_forms = true

Upvotes: 0

Views: 363

Answers (3)

Tarek N. Elsamni
Tarek N. Elsamni

Reputation: 1837

Your logs show this error:

ActionView::Template::Error (Missing partial tweets/_index

That's caused by this code:

addTweet('<%= j render "tweets/index", tweet: @tweet %>');

Apparently, you don't have a partial called tweets/_index to render.

Could you create this file and make sure it's named _index not index?

Upvotes: 0

mgidea
mgidea

Reputation: 494

The error you are getting is the javascript response to the form submitting. This line in particular:

addTweet('<%= j render "tweets/index", tweet: @tweet %>')

is the issue.

ActionView::Template::Error (Missing partial tweets/_index with {:locale=>[:en], :formats=>[:js, :html], :variants=>[], :handlers=>[:raw, :erb, :html, :builder, :ruby, :jbuilder]}

you must not have a app/views/_tweets file in your application

note that render "tweets/index" automatically adds an underscore to the beginning of the filename passed in so tweets/index becomes tweets/_index.

you need to add a partial (a view file with a leading underscore) that renders the index template

Upvotes: 1

Jessiel Heitor Hacke
Jessiel Heitor Hacke

Reputation: 51

I think you got a typo in your js.erb

const tweets = document.getElementById('tweets');
reviews.insertAdjacentHTML('beforeend', reviewHTML);

did you mean tweets instead of reviews in the second line?

also in the js.erb

function refreshForm(innerHTML) {
  const newTweetForm = document.getElementById('new_tweet');
  newTweetForm.innerHTML = innerHTML;
}

But this will render a form inside the form, shouldn't you get the parent element for that. In your case is the class tweet-form.

Upvotes: 0

Related Questions