Home > Software engineering >  What's wrong with my form in Ruby on Rails?
What's wrong with my form in Ruby on Rails?

Time:01-19

I'm trying to implement a prayer request and prayer response form, much like a micropost with a comment on it. The prayer requests are created and deleted as expected, but when I try to post a prayer response, it just reloads the page with no errors and no flash saying that the post was successful. This behavior happens wether the post is valid or not (no errors for a blank response, just a reload of the page) When I use the rails console, I'm able to build and save a prayer response successfully, and it shows up on rails server. What's wrong with my form? Based on the server log, I see that when I try to post a prayer response, it's using the RequestsController instead of the PrayerResponsesController. How do I fix this?

Here's my server log errors:

Started POST "/requests" for 127.0.0.1 at 2023-01-18 16:24:36 -0600
Processing by RequestsController#create as TURBO_STREAM
  Parameters: {"authenticity_token"=>"[FILTERED]", "content"=>"Prayer response...", "request_id"=>"150", "commit"=>"Respond in Prayer"}
  User Load (0.1ms)  SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
  ↳ app/helpers/sessions_helper.rb:18:in `current_user'
  CACHE User Load (0.0ms)  SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
  ↳ app/helpers/sessions_helper.rb:18:in `current_user'
Completed 400 Bad Request in 4ms (ActiveRecord: 0.1ms | Allocations: 2115)


  
ActionController::ParameterMissing (param is missing or the value is empty: request
Did you mean?  request_id):

Here's my code:

controllers/prayer_responses_controller.rb

class PrayerResponsesController < ApplicationController
  before_action :logged_in_user, only: [:create, :destroy]
  before_action :correct_user, only: :destroy

  def create
    @prayer_response = current_user.prayer_responses.build(prayer_response_params)
    if @prayer_response.save
      flash[:success] = "Prayer Response created!"
      redirect_back(fallback_location: root_url)
    else
      render 'static_pages/requests', status: :unprocessable_entity
    end
  end

  def destroy
    @prayer_response.destroy
    flash[:success] = "Prayer Response deleted"
    redirect_back_or_to( root_url, status: :see_other )
  end

  private

    def prayer_response_params
      params.require(:prayer_response).permit(:content, :request_id)
    end

    def correct_user
      @prayer_response = current_user.prayer_responses.find_by(id: params[:id])
      redirect_to root_url, status: :see_other if @prayer_response.nil?
    end
end

views/static_pages/requests.html.erb

<% provide(:title, "Prayer Requests") %>
<div >
  <aside >
    <section >
      <%= render 'shared/request_form' %>
    </section>
  </aside>
  <div >
    <h3>Prayer Requests</h3>
    <% if Request.all != nil %>
        <%= render Request.all %>
    <% end %>
  </div>
</div>

views/requests/_request.html.erb

<li id="request-<%= request.id %>" >
  <%= link_to gravatar_for(request.user, size: 50), request.user %>
  <span ><%= link_to request.user.name, request.user %></span>
  <span ><%= request.content %></span>
  <span >
    Posted <%= time_ago_in_words(request.created_at) %> ago.
    <% if current_user?(request.user) %>
      <%= link_to "delete", request, data: { "turbo-method": :delete,
                                            "turbo-confirm": "Are you sure?"} %>
    <% end %>
  </span>
  <% if current_user != nil %>
  <span>
    <%= render 'shared/prayer_response_form', request_id: request.id %>
  </span>
  <span>
    <% if request.prayer_responses.any? %>
      <ol >
      <% request.prayer_responses.reverse.each do |prayer_response| %>
        <%= render prayer_response %>
      <% end %>
      </ol>
    <% end %>
  </span>
  <% end %>
</li>

views/prayer_responses/_prayer_response.html.erb

<li id="prayer_response-<%= prayer_response.id %>">
  <%= link_to gravatar_for(prayer_response.user, size: 30), prayer_response.user %>
  <span ><%= link_to prayer_response.user.name, prayer_response.user %></span>
  <span ><%= prayer_response.content %></span>
  <span >
    Posted <%= time_ago_in_words(prayer_response.created_at) %> ago.
    <% if current_user?(prayer_response.user) %>
      <%= link_to "delete response", prayer_response, data: { "turbo-method": :delete,
                                            "turbo-confirm": "Are you sure?"} %>
    <% end %>
  </span>
</li>

views/shared/_prayer_response_form.html.erb

<%= form_with(model: @prayer_response) do |f| %>
  <%= render 'shared/error_messages', object: f.object %>
  <center>
    <div >
      <%= f.text_area(:content, placeholder: "Respond to this prayer request...") %>
    </div>
    <div><%= f.hidden_field :request_id, value: request_id %></div>
      <%= f.submit "Respond in Prayer", class: "btn btn-primary" %>
  </center>
<% end %>

models/prayer_response.rb

class PrayerResponse < ApplicationRecord
  belongs_to :user
  belongs_to :request
  default_scope -> { order( created_at: :desc) }
  validates :user_id, presence: true
  validates :request_id, presence: true
  validates :content, presence: true, length: { maximum: 500 }
end

models/request.rb

class Request < ApplicationRecord
  belongs_to :user
  has_many :prayer_responses, dependent: :destroy
  default_scope -> { order(created_at: :desc) }
  validates :user_id, presence: true
  validates :content, presence: true, length: { maximum: 280 }
end

db/migrate/20230113172701_create_prayer_responses.rb

class CreatePrayerResponses < ActiveRecord::Migration[7.0]
  def change
    create_table :prayer_responses do |t|
      t.text :content
      t.references :user, null: false, foreign_key: true
      t.references :request, null: false, foreign_key: true

      t.timestamps
    end
    add_index :prayer_responses, [:user_id, :request_id, :created_at]
  end
end

db/migrate/20230107204925_create_requests.rb

class CreateRequests < ActiveRecord::Migration[7.0]
  def change
    create_table :requests do |t|
      t.text :content
      t.references :user, null: false, foreign_key: true

      t.timestamps
    end
    add_index :requests, [:user_id, :created_at]
  end
end

config/routes.rb

  root   "static_pages#home"
  get    "/help",    to: "static_pages#help"
  get    "/about",   to: "static_pages#about"
  get    "/contact", to: "static_pages#contact"
  get    "/new_public_prayers", to: "static_pages#new_public_prayers"
  get    "/signup",  to: "users#new"
  get    "/login",   to: "sessions#new"
  post   "/login",   to: "sessions#create"
  delete "/logout",   to: "sessions#destroy"
  resources :users do
    member do
      get :following, :followers
    end
  end
  resources :account_activations, only: [:edit]
  resources :password_resets,     only: [:new, :create, :edit, :update]
  resources :prayers,             only: [:create, :destroy]
  resources :requests,            only: [:create, :destroy]
  resources :prayer_responses,    only: [:create, :destroy]
  resources :comments,            only: [:create, :destroy]
  resources :private_prayers,     only: [:create, :destroy]
  resources :relationships,       only: [:create, :destroy]
  get "/private_prayers", to: "static_pages#private_prayers"
  get "/prayers", to: "static_pages#home"
  get "/comments", to: "static_pages#home"
  get "/requests", to: "static_pages#requests"
  get "/prayer_responses", to: "static_pages#requests"
end

CodePudding user response:

The answer, actually, was in the static_pages_controller.rb file... I needed to add @prayer_response = current_user.prayer_responses.build to the requests page's function...

class StaticPagesController < ApplicationController
  def home
    if logged_in?
      @prayer = current_user.prayers.build
      @comment = current_user.comments.build
      @feed_items = current_user.feed.paginate(page: params[:page])
    end
  end

  def help
  end

  def about
  end

  def contact
  end

  def new_public_prayers
  end

  def private_prayers
    if logged_in?
      @private_prayer = current_user.private_prayers.build
    else
      redirect_to root_url
    end
  end

  def requests
    if logged_in?
      @request = current_user.requests.build
      @prayer_response = current_user.prayer_responses.build
    else
      redirect_to root_url
    end
  end

end

This made sure that the proper controller was followed when building a new prayer response, etc.

  • Related