Rails - 如何从单一 Table 继承创建正确类型的对象?
Rails - How to create the right kind of object from Single Table Inheritance?
我已经建立了一个 Rails 项目来使用单一 Table 继承,因为我有两种类型的 User
s - Sender
s 和 Receiver
s。 Sender
有 public_key
属性,Receiver
有 phone_number
属性。他们通过 User
.
共享 name
、email
和 password
属性
我的问题是,在 User
控制器的 create
函数中,我正在尝试创建一种或另一种类型 - Sender
或 Receiver
- 基于我的注册表单上单选按钮的值。
设置如下:
用户模型
class User < ActiveRecord::Base
validates :name, :presence => true, :length => { maximum: 50 }
validates :password, presence: true
self.inheritance_column = :user_type
# We will need a way to know which types with subclass the User model
def self.user_types
%w(Sender Receiver)
end
end
class Sender < User; end
class Receiver < User; end
发件人模型
class Sender < User
validates :public_key, :presence => true
end
接收器型号
class Receiver < User
validates :phone_number, :presence => true, :length => 10
end
用户控制器
class UsersController < ApplicationController
# before_action :set_user, only: [:show, :edit, :update, :destroy]
before_action :set_user_type
def index
@users = user_type_class.all
end
def show
@user = User.find(params[:id])
end
def new
@user = User.new
end
def create
if(user_type.eql? "receiver")
@user = Receiver.new(user_params)
else
@user = Sender.new(user_params)
end
...
private
# allow views to access user_type
def set_user_type
@user_type = user_type
end
def user_type
User.user_types.include?(params[:type]) ? params[:type] : "User"
end
def user_type_class
user_type.constantize
end
# Use callbacks to share common setup or constraints between actions.
def set_user
@user = User.find(params[:id])
end
def user_params
params.require(:user).permit(:name, :email, :password, :confirmation_password, :user_type)
end
end
新用户表单
<%= form_for(@user) do |f| %>
...
<div class="user-type">
<%= f.label :user_type, class: 'form-control' %>
<%= radio_button_tag(:user_type, "sender") %>
<%= label_tag(:user_type_sender, "I am a Sender") %>
<%= radio_button_tag(:user_type, "receiver") %>
<%= label_tag(:user_type_receiver, "I am a Receiver") %>
</div>
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %>
</div>
...
<% end %>
在 User
控制器的 create
方法中,我尝试使用此 if
语句创建正确的 User
类型:
if(user_type.eql? "receiver")
@user = Receiver.new(user_params)
else
@user = Sender.new(user_params)
根据此处 User
表格中记录的值:
<%= radio_button_tag(:user_type, "sender") %>
<%= label_tag(:user_type_sender, "I am a Sender") %>
<%= radio_button_tag(:user_type, "receiver") %>
<%= label_tag(:user_type_receiver, "I am a Receiver") %>
然而,我总是从else
语句中得到一个Sender
类型的对象。我认为这意味着我的 if
语句 if(user_type.eql? "receiver")
有问题;但是,我不知道是什么。
想法?
首先,我认为您不需要 set_user_type
方法,因为您没有使用其设置的 @user_type
变量。也从控制器顶部取出before_action
。
其次,在 user_type
方法中,您需要将 params[:type]
更改为 params[:user_type]
,因为这是 HTML.
中单选按钮标签的名称
def user_type
User.user_types.include?(params[:user_type]) ? params[:user_type] : "User"
end
第三,你还需要将单选按钮标签的值属性大写为"Sender"和"Receiver",因为这就是你在User.user_types
数组中的内容。
<%= radio_button_tag(:user_type, "Sender") %>
<%= radio_button_tag(:user_type, "Receiver") %>
免责声明:未经测试,但应该可以解决您的问题。
我已经建立了一个 Rails 项目来使用单一 Table 继承,因为我有两种类型的 User
s - Sender
s 和 Receiver
s。 Sender
有 public_key
属性,Receiver
有 phone_number
属性。他们通过 User
.
name
、email
和 password
属性
我的问题是,在 User
控制器的 create
函数中,我正在尝试创建一种或另一种类型 - Sender
或 Receiver
- 基于我的注册表单上单选按钮的值。
设置如下:
用户模型
class User < ActiveRecord::Base
validates :name, :presence => true, :length => { maximum: 50 }
validates :password, presence: true
self.inheritance_column = :user_type
# We will need a way to know which types with subclass the User model
def self.user_types
%w(Sender Receiver)
end
end
class Sender < User; end
class Receiver < User; end
发件人模型
class Sender < User
validates :public_key, :presence => true
end
接收器型号
class Receiver < User
validates :phone_number, :presence => true, :length => 10
end
用户控制器
class UsersController < ApplicationController
# before_action :set_user, only: [:show, :edit, :update, :destroy]
before_action :set_user_type
def index
@users = user_type_class.all
end
def show
@user = User.find(params[:id])
end
def new
@user = User.new
end
def create
if(user_type.eql? "receiver")
@user = Receiver.new(user_params)
else
@user = Sender.new(user_params)
end
...
private
# allow views to access user_type
def set_user_type
@user_type = user_type
end
def user_type
User.user_types.include?(params[:type]) ? params[:type] : "User"
end
def user_type_class
user_type.constantize
end
# Use callbacks to share common setup or constraints between actions.
def set_user
@user = User.find(params[:id])
end
def user_params
params.require(:user).permit(:name, :email, :password, :confirmation_password, :user_type)
end
end
新用户表单
<%= form_for(@user) do |f| %>
...
<div class="user-type">
<%= f.label :user_type, class: 'form-control' %>
<%= radio_button_tag(:user_type, "sender") %>
<%= label_tag(:user_type_sender, "I am a Sender") %>
<%= radio_button_tag(:user_type, "receiver") %>
<%= label_tag(:user_type_receiver, "I am a Receiver") %>
</div>
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %>
</div>
...
<% end %>
在 User
控制器的 create
方法中,我尝试使用此 if
语句创建正确的 User
类型:
if(user_type.eql? "receiver")
@user = Receiver.new(user_params)
else
@user = Sender.new(user_params)
根据此处 User
表格中记录的值:
<%= radio_button_tag(:user_type, "sender") %>
<%= label_tag(:user_type_sender, "I am a Sender") %>
<%= radio_button_tag(:user_type, "receiver") %>
<%= label_tag(:user_type_receiver, "I am a Receiver") %>
然而,我总是从else
语句中得到一个Sender
类型的对象。我认为这意味着我的 if
语句 if(user_type.eql? "receiver")
有问题;但是,我不知道是什么。
想法?
首先,我认为您不需要 set_user_type
方法,因为您没有使用其设置的 @user_type
变量。也从控制器顶部取出before_action
。
其次,在 user_type
方法中,您需要将 params[:type]
更改为 params[:user_type]
,因为这是 HTML.
def user_type
User.user_types.include?(params[:user_type]) ? params[:user_type] : "User"
end
第三,你还需要将单选按钮标签的值属性大写为"Sender"和"Receiver",因为这就是你在User.user_types
数组中的内容。
<%= radio_button_tag(:user_type, "Sender") %>
<%= radio_button_tag(:user_type, "Receiver") %>
免责声明:未经测试,但应该可以解决您的问题。