简体   繁体   中英

Nested form with STI and devise

Quite a few questions on this topic, but I can't find a solution to my issue.

I have a Devise model called User which (using Single table inheritance) has a subclass called Student (among others)

Student has a 'has_one' association with a class called Vehicle.

My model set up:

class User < ActiveRecord::Base
    devise :database_authenticatable, :registerable,
     :recoverable, :rememberable, :trackable, :validatable
end

class Student < User
    has_one :vehicle, :dependent => :destroy
    accepts_nested_attributes_for :vehicle, allow_destroy: true
end

class Vehicle < ActiveRecord::Base
    belongs_to :student
end

I want to create a nested form which has the User fields, Student fields, and then the vehicle fields, ie something like this:

<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>

*** User fields***

    <% if @class == "Student" %>

    *** Student fields***

        <% f.fields_for :vehicle do |builder| %>

             *** Vehicle fields***

            <%= f.hidden_field :_destroy %>
            <%= link_to "remove", '#', class: "remove_fields" %>

        <% end %>

        <%= link_to_add_fields "Add vehicle", f, :vehicle %>

     <% end %>
<% end %>

The issue is that I get an undefined method error for :vehicle on a User object. This is not surprising given that I haven't actually related Vehicles to Users in my models. I'm just not sure how to do it.

My users/registrations controller has the following sign-up method:

# GET /users/sign_up

    def new
        @class = params[:class]

        build_resource({})
        respond_with self.resource
    end

Given devise is set up for the User class, I think this creating a resource of type 'user' and passing it through to my view, which then can't link it to a 'Vehicle'.

Is there any way to create the required associations or to create a resource of type 'student' to pass through to the view?

This might not be an answer (I'll delete if required), but I'll give you my observations & ideas:

--

Create

You're currently using users#sign_up as the controller method, yet you wish to populate the Student class?

I don't know how Devise will work in this nature, but I do know that if you want to use STI's correctly, you'll be best using the native objects directly. For example, if you wish to create a student, you'll be best using the following:

#app/controllers/students_controller.rb
class StudentsController < InheritedResources::Base #-> assuming you wish to use Inherited Resources

   def new
      new!(@student.build_vehicle)
   end

   private

   def permitted_params
      params.permit(:student => :your, :student, :params, vehicle_attributes: [:vehicle, :attributes])
   end    
end 

This will give you the ability to use the same form as you were using, except it will only show the student records:

#app/views/students/new.html.erb
<%= form_for resource, as: resource_name do |f| %>
   <% if resource_class == "Student" %>
       ...
   <% end %>
<% end %>

This will allow you to create a new Student object (which you weren't before)

I don't know this will work with Devise, but I know for sure that if you send the request as I have outlined above, you'll be able to create a Student object, and consequently, be able to create the functionality you need

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