Rails设计多态 – 使用Ajax渲染部分渲染
我已经从这个答案实现了多个模型的设计注册。 这个tuts从路径获取params user_type
。 我想用select user_type
更改它。 因此,当我在select_tag
上选择一个值时,将获得一个param user_type。
我有一些代码看起来像:
的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
Add User
resource_name, :url => registration_path(resource_name)) do |f| %>
$("#user_usertype").on('change', function() { var s = $(this).val(); $.ajax({ type: 'GET', url: 'http://localhost:3000/cp/select/' + s, dataType: "HTML" }); });
selectuser.js.erb
child_class_name.underscore + '_fields', :locals => {:f => rf} end %> $("#selectuser").append("");
当我选择管理员值时,记录:
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)
但_admin_fields.html.erb
没有出现在#selectuser
你在这里混淆了几件事。
- 您的路线定义默认值
如果您需要从下拉列表中进行选择,则无需在此处定义默认值。 它只会让事情复杂化
match '/add_user' => 'registrations#new', :user => { :usertype => nil } match '/select/admin' => 'registrations#selectuser', :user => { :usertype => 'admin' } match '/select/player' => 'registrations#selectuser', :user => { :usertype => 'player' }
- 你没有使用正确的表格助手
如果你想获得params[:user][:usertype]
的输出,你需要使用f.select
。 如果您的模型没有这样的属性,您可以将它作为attr_accessor
添加到您的模型中。
<%= label :usertype, "Select User Type" %>
<%= select_tag(:usertype, options_for_select([['-- User Type --', nil], ['Admin', 'admin'], ['Player', 'player']], selected: '-- User Type --' )) %>
我认为你有很多问题,但最重要的是:
nesteds = fields_for child_class_name.constantize.new do |rf| render :partial => child_class_name.underscore + '_fields', :locals => {:f => rf}
您正尝试在变量中呈现“ fields_for
”帮助器。 问题是这个变量被视为一个字符串,这意味着它不再是一个帮助器,并且不会导致出现fields_for
元素。 这是因为我们不知道你的系统的哪个部分不起作用 –
你的Ajax被解雇了吗? 您的路线是否正确发送请求?
就个人而言,我会重新考虑你的系统的这部分是如何工作的
我将从渲染的selectuser.js.erb中删除逻辑,并将其放入控制器,如下所示:
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
然后在你的JS中,你可以让JS做它诞生的东西:
$("#selectuser").html("<%=j render :partial => @render, locals: {:f = @rf} %>");
这意味着在您的child_class_name_fields.html.erb中,您需要具有以下内容:
<%= f.fields_for child_class_name.constantize.new do |rf| %> <%= rf.text_field :name %> <% end %>
更新
我现在正在努力解决这个问题,因为我会完全不同地做到这一点。 我会将整个逻辑移动到控制器中,并且只通过:render函数将变量发送到partial。
我不喜欢你想要动态生成“f.fields_for”的想法 – 它应该已经设置,你只需要更改该块内的字段。 这是一个被称为DRY(不要重复自己)编程的原则。 如果你愿意,我可以为你编写我喜欢的版本,而不是尝试monkeypatch这个?
在您的控制器文件中返回
render json: {"fields" => render_to_string(partial: "admin_fields") }
当控制器返回json到你的ajax函数时注入以下 –
$('#selectuser').html(fields)
当您尝试渲染部分时,您必须添加=:
<%= params[:user][:usertype] ||= 'admin' # ^ This makes whatever is being returned in this block to be added to the output
- 如何在Rails 3中使用AJAX请求实现重定向响应?
- 选择’file_field’文件时检查文件扩展名,并使用Ruby on Rails显示错误消息(如果有)
- Rails与ajax和非ajax按钮一起形成
- 在Rails中通过JS设计注册#update
- Ajaxified Star Rating System未正确更新
- 如何通过jquery / ajax作为JSON对象将数据发送和存储到rails?
- Ruby on Rails实时搜索(过滤)
- ActionController :: UnknownFormat with format.js for ajax implementation(Rail 4)
- Rails Paperclip和AJAX表单