Rails 4.0设计3.x并将自定义列添加到STI用户模型

时间:2014-01-12 23:52:37

标签: ruby-on-rails devise controller

我有一个运行设计3.x的rails 4应用程序,我在向我的播放器模型添加:first_name列时遇到问题。我有2个独立的模型,它们继承自User模型 - PlayerCoach

我关注this 12 spokes帖子,但在开发模式下呈现注册表单时遇到问题。

我有一个班级PlayerParameterSanitizer来覆盖设计signup action并添加:first_name参数

class PlayerParameterSanitizer < Devise::ParameterSanitizer
  def sign_up
    default_params.permit(:type, :email, :password, :password_confirmation, :first_name)
  end
end

我在应用程序控制器中创建了这个类的新对象

class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception

  protected

  def devise_parameter_sanitizer
    if resource_class == Player
      PlayerParameterSanitizer.new(Player,:player,params)
    elsif resource_class == Coach
      CoachParameterSanitizer.new(Coach,:coach,params)
    else
      super
    end    
  end

end

我正在config/initializers/sanitizers.rb

中的初始化程序中加载清洁剂
require "#{Rails.application.root}/lib/player_sanitizer.rb"

然而,我仍然得到了

undefined method `first_name' for #<Player:0x00000101cafab0>
view/players/registrations/new.html.erb页面上的

。我在这里缺少什么?

更新

db schema

  create_table "players", force: true do |t|
    t.datetime "created_at"
    t.datetime "updated_at"
    t.string   "first_name"
  end

更新#2

devise_for :players, :controllers => {:registrations => "players/registrations",
                                        :sessions => "players/sessions",
                                        :passwords => "players/passwords"}

不相关理智的模型

class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable

end

从User继承的Player类。

class Player < User

end

更新#3

我不应该以这种方式使用STI,我不认为。

我希望教练和玩家分享Devise Auth功能,但玩家将有额外的领域到教练(俱乐部,职位,年份等)

使用STI for rails 4,所有属性都将存储在User表中。但是这意味着教练会拥有这些领域,但是在其位置保存,因为对于位置,当前俱乐部等的东西都没有。

这似乎不正确..

基本上,我希望Coach和Player都能从User继承,以实现设计功能。但是,我希望玩家除了Coach之外还有几个领域。

3 个答案:

答案 0 :(得分:2)

您也可以使用多态,并且不会共享数据库属性。如下所示:

class Login < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable

  belongs_to :user, polymorphic: true
end

class Player < ActiveRecord::Base
   has_one :login, as: :user
end


class Coach < ActiveRecord::Base
   has_one :login, as: :user
end

这只是为了给你一个粗略的想法。请注意,我没有尝试过任何此类操作,如果您在Devise中使用未命名为User的类,则可能需要特别小心。祝你好运!

答案 1 :(得分:1)

您需要确保您的路由器也使用了正确的控制器。否则它将从Devise(这是一个Rails引擎)加载控制器,在你的路由器中尝试这个:

devise_for :users, :controllers => { registrations: 'users/registrations' }

否则,我也会看一下这个问题:https://stackoverflow.com/a/19793371/103739

答案 2 :(得分:0)

在进一步研究(http://www.martinfowler.com/eaaCatalog/singleTableInheritance.html)之后,似乎应该将所有属性添加到User表中。这将导致(在我的情况下)Coach nil的其他字段Player的{​​{1}}值。

这可能导致以后出现缩放问题,并且与我最初想到的强力障碍+轨道4的设计无关。