Rails Devise Polymorphic - Get Render Partial Using Ajax

☆樱花仙子☆ 提交于 2020-01-03 10:05:10

问题


I have implement devise registration with multiple model from this answer. This tuts get params user_type from path. I want to change this with select user_type. So a param user_type will get when I select a value on select_tag.

I have some code looks like :

routes.rb

   namespace :cp do
    devise_scope :user do
     match '/add_user' => 'registrations#new'
     match '/select/admin' => 'registrations#selectuser', :user => { :usertype => 'admin' }
     match '/select/player' => 'registrations#selectuser', :user => { :usertype => 'player' }
    end
   end

registrations_controller.rb

  def selectuser

    respond_to do |format|
      format.js
    end
  end

new.html.erb

<h2>Add User</h2>

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

  <div><%= f.label :username, "Username" %><br />
  <%= f.text_field :username %></div>

  <div><%= f.label :email, "Email" %><br />
  <%= f.email_field :email %></div>

  <div><%= f.label :password, "Password" %><br />

  <%= f.password_field :password %></div>

  <div><%= f.label :password_confirmation, "Password Confirmation" %><br />
  <%= f.password_field :password_confirmation %></div>

  <div><%= f.label :usertype, "Select User Type" %><br />
  <%= f.select(:usertype, options_for_select([['-- User Type --', nil], ['Admin', 'admin'], ['Player', 'player']], selected: '-- User Type --' )) %>
   </div> 

   <div id="selectuser">
   </div>
  <% end %>

  <div><%= f.submit "Submit" %></div>
<% end %>

<script type="text/javascript">
$("#user_usertype").on('change', function() {
   var s = $(this).val();
       $.ajax({
              type: 'GET',
              url: 'http://localhost:3000/cp/select/' + s,
              dataType: "HTML"
              });
});
</script>

selectuser.js.erb

<%  params[:user][:usertype] ||= 'admin'

    if ["admin", "player"].include? params[:user][:usertype].downcase
      child_class_name = params[:user][:usertype].downcase.camelize
      usertype = params[:user][:usertype].downcase
    else
      child_class_name = "Admin"
      usertype = "admin"
    end


   nesteds = fields_for child_class_name.constantize.new do |rf|
     render :partial => child_class_name.underscore + '_fields', :locals => {:f => rf}
   end
%>
$("#selectuser").append("<%= j nesteds %>");

When I select admin value, log :

Started GET "/cp/select/admin" for 127.0.0.1 at 2013-10-21 17:00:04 +0700
Processing by Cp::RegistrationsController#selectuser as HTML
  Parameters: {"user"=>{"usertype"=>"admin"}}
  Rendered cp/registrations/_admin_fields.html.erb (4.0ms)
  Rendered cp/registrations/selectuser.js.erb (7.0ms)
Completed 200 OK in 22ms (Views: 22.0ms | ActiveRecord: 0.0ms)

But _admin_fields.html.erb not appear on #selectuser


回答1:


you are mixing up several things here.

  • your routes define a default

if you need to select from a dropdown, there is no need to define a default value here. it just complicates things

 match '/add_user' => 'registrations#new', :user => { :usertype => nil }
 match '/select/admin' => 'registrations#selectuser', :user => { :usertype => 'admin' }
 match '/select/player' => 'registrations#selectuser', :user => { :usertype => 'player' }
  • you are not using the right form helpers

you need to use f.select if you want to get an output of params[:user][:usertype]. if your model does not have such a property, you can add it as an attr_accessor to your model.

<%= label :usertype, "Select User Type" %><br />
<%= select_tag(:usertype, options_for_select([['-- User Type --', nil], ['Admin', 'admin'], ['Player', 'player']], selected: '-- User Type --' )) %>



回答2:


I think you've got a lot of problems, but the biggest is here:

nesteds = fields_for child_class_name.constantize.new do |rf|
render :partial => child_class_name.underscore + '_fields', :locals => {:f => rf}

You're trying to render a "fields_for" helper in a variable. The problem is this variable is treated as a string, which means that it's no longer a helper, and won't cause the fields_for element to appear. This is further to the fact that we don't know what part of your system is not working --

Is your Ajax firing? Are your routes sending the request correctly?


Personally, I would re-think how this part of your system works

I would remove the logic from your rendered selectuser.js.erb, and put it into the controller, like this:

  def selectuser

  params[:user][:usertype] ||= 'admin'

    if ["admin", "player"].include? params[:user][:usertype].downcase
      child_class_name = params[:user][:usertype].downcase.camelize
      usertype = params[:user][:usertype].downcase
    else
      child_class_name = "Admin"
      usertype = "admin"
    end

    respond_to do |format|
      format.js { @render = child_class_name.underscore + '_fields', @rf = rf}
    end
  end

Then in your JS, you'd be able to let JS do what it was born to:

$("#selectuser").html("<%=j render :partial => @render, locals: {:f = @rf} %>");

This means that in your child_class_name_fields.html.erb, you need to have something like this:

<%= f.fields_for child_class_name.constantize.new do |rf| %>
    <%= rf.text_field :name %>
<% end %>

Update

I am actually struggling with this now, because I would do it totally differently. I would move the entire logic into the controller, and only send variables to the partial through the :render function.

I don't like the idea you're trying to generate "f.fields_for" on the fly -- it should be set already, and you only change the fields inside that block. It's a principle known as DRY (don't repeat yourself) programming. If you want, I can write my preferred version for you, instead of trying to monkeypatch this one?




回答3:


In your controller file return

render json: {"fields" => render_to_string(partial: "admin_fields") }

when the controller returns json to your ajax function inject with the following -

$('#selectuser').html(fields)



回答4:


You have to add an = when you're trying to render your partial:

<%=  params[:user][:usertype] ||= 'admin'
# ^ This makes whatever is being returned in this block to be added to the output


来源:https://stackoverflow.com/questions/19446624/rails-devise-polymorphic-get-render-partial-using-ajax

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!