简体   繁体   中英

Rails form that requires multiple parameters from different models

I'm currently practicing how to make a pedigree system, I have successfully implemented users who own dogs, but I want those users to be able to create a pedigree relationship to other dog's profiles like in pic related: My view

My issue is that when I click the Submit button to create the relationship (or at least know if it works) I get a "The action 'new' could not be found for PedigreeController" error message. Here is my controller and as you can see I only have a create and a destroy method. I tried changing the url in the view to create but without luck. I have also added resources :pedigree to my route file.

 class PedigreeController < ApplicationController
  def create
    @dog = Dog.find(params[:dog_id])
    #@pedigree = pedigrees.build(dog_id: @dog.id, relative_id: @dog.id, relation_name: :string)
    @pedigree = @dog.build_pedigree(pedigree_params)
    if @pedigree.save
      flash[:success] = "Dog relative added."
      redirect_to access_dogmenu_path
    else
      flash[:danger] = "Unable to add this dog as relative"
      redirect_to access_dogmenu_path
    end
  end

  def destroy
    @pedigree = @dog.pedigrees.find(params[:id])
    @pedigree.destroy
    flash[:success] = "Relative removed."
    redirect_to access_dogmenu_path
  end

  private

  def pedigree_params
    params.require(:pedigree).permit(:dog_id, :relative_id, :relation_name)
  end
end

I have made a pedigree.rb model which is used to create the dogs relationships.

class Pedigree < ActiveRecord::Base
  belongs_to :dog
  belongs_to :relative, class_name: Dog
end

This is the dog.rb model

class Dog < ActiveRecord::Base
  belongs_to :user
  has_many :pedigrees
  has_many :relatives, through: :pedigrees, dependent: :destroy
end

Here is what I have currently in my view (which shows in every dog profile):

...
<h3>Relatives: </h3>
  <ul>
   <% for pedigree in @dog.pedigrees %>
     <li>
     <%= pedigree.relative.dname %>'s - <%= pedigree.relative.relation_name %>
                     <%= link_to "Remove", pedigree, method: :delete %>
      </li>
   <% end %>
   </ul>
<h4>Add this dog as your dog's relative: </h4>
  <%= form_for(Pedigree.new, url: new_pedigree_path) do |p| %>
  Select your dog:
  <%= p.collection_select(:dog_id, @dogs,:id, :dname, :prompt => "Select your dog") %><br>
  Select your dog relation to the dog from this profile:
  <%= select_tag(:relation_id, options_for_select([['Sibling', 1], ['Parent', 2], ['Grandparent', 3], ['Great-grandparent', 4], ['Child', 5], ['Grandchild', 6], ['Great-grandchild', 7]])) %><br>
 <%= p.submit 'Add Relation' %>
 <% end %>
...

To create a pedigree relation 3 things are needed:

  1. The dog_id of the current user's dog of choice (The collection_select seems to be working).

  2. The relative_id of the dog that will become a relative, in this case the relative_id should be taken straight from the show page for example http://localhost:3000/dogs/2 would be sending dog_id=2 into the form. Does anybody know how would I go about including this in my form?

  3. the relation_name like sibling, parent, etc. The drop down selector seems to be working ok.

Any help is greatly appreciated.

An html form looks like this:

<form method="post" action="/some/url">
  ...
  <input type="submit" value="Add Relation" />
</form>

And when you click on the Submit button, a request is sent to the url specified in the action attribute of the <form> tag.

You set the action attribute to:

url: new_pedigree_path

And, when you create the route:

resources :pedigree

you get the following path helpers:

photos_path returns /photos
new_photo_path returns /photos/new
edit_photo_path(:id) returns /photos/:id/edit (for instance, edit_photo_path(10) returns /photos/10/edit)
photo_path(:id) returns /photos/:id (for instance, photo_path(10) returns /photos/10)

http://guides.rubyonrails.org/routing.html#path-and-url-helpers

So, the url you set for the action attribute is: /pedigree/new , which tries to hit the new() action in the PedigreeController .

By default, form_for() creates a form with the action attribute set to /pedigree . See here: http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html

And, your resources route gets you the following url-to-action mappings:

在此处输入图片说明 http://guides.rubyonrails.org/routing.html#crud-verbs-and-actions

If you check the chart for /pedigree when part of a post request--which is the type of request that form_for() sends(see the resulting html at the link above again)--the request will route to the create() action in the PedigreeController.

The relative_id of the dog that will become a relative,... Does anybody know how would I go about including this in my form?

  1. When you create the form, you can create a hidden form field and set its value to the relative_id. Then when the user submits the form, the name/value pair will be in the params hash.

  2. In the action that sends the form back, you can add the relative_id to the sessions hash, then look it up again when the user submits the form.

  3. In the action that sends the form back, you can set a cookie in the response: cookies[:name] = value . Then when the user submits the form, the cookie will be sent back to you in the headers of the request, and you can retrieve the value from the cookies hash.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM