mardi 9 janvier 2018

How to bypass the form and pass information straight to the create action with a link_to in Rails

Setup

App has 3 models. A Member model, a Support model and an Involvement model. The member model keeps track of all of the users for my web app. The support model keeps track of the many different ways a user can support our organization. The Involvement model connects the other two models by keeping track of the member_id and support_id showing in which support areas the member is active.

Current Functionality

In a member's profile, they can look at a support tab which queries all the different areas that they can support from the support model. It then checks if there is a involvement that includes both their id and the id of that support area and states whether they are currently supporting or not.

Desired Outcome

I want to have a link that they can click on that will either create or delete an involvement. So, if they are currently supporting financially, it will state that they are and provide a link to stop supporting that way, which when clicked will delete the involvement record; and vise versa, if they are not supporting financially, a link will show to start supporting and that link will create the involvement record. (Ultimately I am going to integrate a toggle function which will allow a member to just toggle back and forth, but I need to work this out first.)

Question

Is there a way to send params via link_to to the 'create' or 'destroy' actions to bring about this functionality? Currently I am doing the following but get an error:

<%= 
    link_to "Start Supporting", 
    involvements_path(member_id: current_member.id, 
                      support_id: support_area.id), 
    method: :post 
%>

Error

ActionController::ParameterMissing in InvolvementsController#create
param is missing or the value is empty: involvement

When I do byebug, I get the following output for params:

(byebug) params
<ActionController::Parameters {"_method"=>"post", 
                               "member_id"=>"1", 
                               "support_id"=>"2",                                                                                                                                             
                               "controller"=>"involvements", 
                               "action"=>"create"} 
                                permitted: false>

So, it doesn't look like params is empty... is it not passing through the whitelist? Any ideas?

Code

rake routes

    involvements GET    /involvements(.:format)           involvements#index
                 POST   /involvements(.:format)           involvements#create
 new_involvement GET    /involvements/new(.:format)       involvements#new
edit_involvement GET    /involvements/:id/edit(.:format)  involvements#edit
     involvement GET    /involvements/:id(.:format)       involvements#show
                 PATCH  /involvements/:id(.:format)       involvements#update
                 PUT    /involvements/:id(.:format)       involvements#update
                 DELETE /involvements/:id(.:format)       involvements#destroy

app/models/involvement.rb

class Involvement < ApplicationRecord
  belongs_to :member
end

db/schema.rb

create_table "involvements", force: :cascade do |t|
   t.bigint "member_id"
   t.integer "support_id"
   t.datetime "created_at", null: false
   t.datetime "updated_at", null: false
   t.index ["member_id"], name: "index_involvements_on_member_id"
end

app/views/profiles/show.html.erb

<% if @user == 'Owner' %>

  <% if @show_page == 'account' %>
    <%= render 'profile_account' %>
  <% elsif @show_page == 'main' %>
    <%= render 'profile_main', locals: { profile: @profile, 
                                         user: @user } %>
  <% elsif @show_page == 'support' %>
    <%= render 'profile_support', locals: { profile: @profile, 
                                            user: @user, 
                                            supports: @supports, 
                                            involvement: @involvements 
                                          } %>
  <% else %>
    <script type="text/javascript">
        window.location.href="<%= 
               member_profile_path(current_member.profile.u_name) 
        %>"
    </script>
  <% end %>

<% else %>
  <%= render 'profile_main', locals: { profile: @profile, 
                                       user: @user } %>
<% end %>

app/views/profiles/_profile_support.html.erb

<h1>This is the Support Page</h1>

<table style="width:50%">
  <tr>
    <th>Support Area</th>
    <th>Support Status</th>
    <th>Change Status</th>
  </tr>
  <% @supports.each do |support_area| %>
    <tr>  
      <th>
        <%= link_to support_area.title, support_page_path(support_area.title) %>
      </th>
      <th>
        <% @presence_check = Involvement.exists?(member_id: current_member.id, 
                                                 support_id: support_area.id) %>
        <% if @presence_check %>
          Supporting
        <% else %>
          Not Supporting
        <% end %>
      </th>
      <th>
        <%= link_to "Start Supporting", 
                    involvements_path(member_id: current_member.id, 
                                      support_id: support_area.id), 
                    method: :post %>
      </th>
    </tr>
  <% end %>
</table>

app/controllers/involvements_controller.rb

class InvolvementsController < ApplicationController
  before_action :set_involvement, only: [:show, :edit, :update, :destroy]

  def index
    @involvements = Involvement.all
  end

  def show
  end

  def new
    @involvement = Involvement.new
  end

  def edit
  end

  def create    
    @involvement = Involvement.new(involvement_params)
    # byebug
    respond_to do |format|
      if @involvement.save
        format.html { redirect_to @involvement, 
                      notice: 'Involvement was successfully created.' }
      else
        format.html { render :new }
      end
    end
  end

  def update
    respond_to do |format|
      if @involvement.update(involvement_params)
        format.html { redirect_to @involvement, 
                      notice: 'Involvement was successfully updated.' }
      else
        format.html { render :edit }
      end
    end
  end

  def destroy
    @involvement.destroy
    respond_to do |format|
      format.html { redirect_to involvements_url, 
                    notice: 'Involvement was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_involvement
      @involvement = Involvement.find(params[:id])
    end

    # Never trust parameters from the scary internet, 
    # only allow the white list through.

    def involvement_params
      # byebug
      params.require(:involvement).permit(:member_id, :support_id)
    end
end

Aucun commentaire:

Enregistrer un commentaire