设计多种用户类型的多态关联,形成部分麻烦

时间:2013-02-26 06:51:43

标签: ruby-on-rails devise

我一直在与我的部分表格领域的问题作斗争;错误是:

#的未定义方法`input'

背景:

我已经从这个很棒的堆栈溢出帖子中建立了一个多态关联:

Multiple user models with Ruby On Rails and devise to have separate registration routes but one common login route

+1给Vapire和朋友这件事,干得好。

有一些错误与注册控制器中重写的create方法有关。

为了清晰起见,我将把拼图的各个部分包括在内:

迁移:

def change
    add_column :users, :rolable_id, :integer 
    add_column :users, :user_type, :string 
end

应用程序/模型/ user.rb

class User < ActiveRecord::Base
  # the usual devise stuff....

  belongs_to :rolable, :polymorphic => true

  def coach?
    if user_type == 'Coach'
      true
    end
  end

  def player?
    if user_type == 'Player'
      true
    end
  end

end

应用程序/模型/ coach.rb

class Coach < ActiveRecord::Base
  attr_accessible :url
  has_one :user, :as => :rolable
end

app / controllers / registrations_controller.rb(从github设计源更新)

class RegistrationsController < Devise::RegistrationsController
  def create
    build_resource

    # customized code begin

    # crate a new child instance depending on the given user type
    child_class = params[:user][:user_type].camelize.constantize
    resource.rolable = child_class.new(params[child_class.to_s.underscore.to_sym])

    # first check if child instance is valid
    # cause if so and the parent instance is valid as well
    # it's all being saved at once
    valid = resource.valid?
    valid = resource.rolable.valid? && valid

    # customized code end

    if valid && resource.save    # customized code
      if resource.active_for_authentication?
        set_flash_message :notice, :signed_up if is_navigational_format?
        sign_up(resource_name, resource)
        respond_with resource, :location => after_sign_up_path_for(resource)
      else
        set_flash_message :notice, :"signed_up_but_#{resource.inactive_message}" if is_navigational_format?
        expire_session_data_after_sign_in!
        respond_with resource, :location => after_inactive_sign_up_path_for(resource)
      end
    else
      clean_up_passwords resource
      respond_with resource
    end
  end
end

应用程序/配置/ routes.rb中

devise_for :users, :path_names => {
    :sign_in => 'login', 
    :sign_out => 'logout'
  }, :controllers => {
      :registrations => "registrations"
  }

  resources :users

  devise_scope :user do
    match 'player/sign_up' => 'registrations#new', :user => { :user_type => 'player' }
    match 'coach/sign_up' => 'registrations#new', :user => { :user_type => 'coach' }
  end

共享注册表单, 应用程序/视图/设计/注册/ new.html.erb

<h3>Sign up: 
<% if params[:user][:user_type].downcase.eql? 'coach' %>
  Coach account
<% else %>
  Player account
<% end %>
</h3>

<%
  params[:user][:user_type] ||= 'player'

  if ["player", "coach"].include? params[:user][:user_type].downcase
    child_class_name = params[:user][:user_type].downcase.camelize
    user_type = params[:user][:user_type].downcase
  else
    child_class_name = "Player"
    user_type = "player"
  end

  resource.rolable = child_class_name.constantize.new if resource.rolable.nil?
%>

<div class="row">
  <div class="span6">

    <%= simple_form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => {:class => 'form-horizontal' } ) do |f| %>
      <%= my_devise_error_messages! %>

      <div class="form-inputs">

        <%= f.input :name, :wrapper => :prepend do %>
          <span class="add-on"><i class="icon-user"></i></span><%= f.input_field :name, :autofocus => true, :required => true, :size => '' %>
        <% end %>

        <%= f.input :nickname, :wrapper => :prepend do %>
          <span class="add-on"><i class="icon-tag"></i></span><%= f.input_field :nickname, :required => false, :size => '' %>
        <% end %>

        <%= f.input :email, :wrapper => :prepend do %>
          <span class="add-on"><i class="icon-envelope"></i></span><%= f.input_field :email, :required => true, :size => '' %>
        <% end %>

        <%= f.input :password, :wrapper => :prepend do %>
          <span class="add-on"><i class="icon-eye-close"></i></span><%= f.input_field :password, :required => true, :size => '' %>
        <% end %>

        <%= f.input :password_confirmation, :wrapper => :prepend do %>
          <span class="add-on"><i class="icon-eye-close"></i></span><%= f.input_field :password_confirmation, :required => true, :size => '' %>
        <% end %>

        <% # customized code begin %>
        <%= fields_for resource.rolable do |rf| %>
          <% render :partial => "#{child_class_name.underscore}_fields", :locals => { :f => rf } %>
        <% end %>

        <%= hidden_field :user, :user_type, :value => user_type %>
        <% # customized code end %>
      </div>

      <div class="form-actions">
        <%= f.button :submit, "Sign up", :class => 'btn-primary' %>
      </div>
    <% end %>
    <%= render "devise/shared/links" %>
  </div>

现在,_coach部分的工作版本:

<%= f.label :url %>
<%= f.text_field :url %>

但我的问题是表单标签的twitter bootstrap样式,正如您在上面的主窗体中所看到的那样。

当我在partial中尝试相同类型的标记时:

<%= f.input :url, :wrapper => :prepend do %>
  <span class="add-on"><i class="icon-globe"></i></span><%= f.input_field :url, :required => false %>
<% end %>

错误是: 用于#的未定义方法`input'

在我看来,部分中我需要的对象超出了范围。 如果是这样,为什么f.text_field可以在工作示例中看到。

困惑的是我。

任何帮助,阅读建议都会很棒

0 个答案:

没有答案