繁体   English   中英

带有单个控制器的STI

[英]STI with a Single Controller

我有几个模型(用户,目标),我的目标模型有几个子类型(运动,瑜伽等)

用户可以有很多目标,但每种目标只能有一个。

class User < ActiveRecord::Base
    has_many :goals, dependent: :destroy
    has_one :exercise
    has_one :water
    has_one :yoga

    def set_default_role
        self.role ||= :user
    end
end

class Goal < ActiveRecord::Base
    self.inheritance_column = :description

    belongs_to :user
    validates :user_id, presence: true
    validates :description, presence: true
end

目标的子类就是这样

class Exercise < Goal
    belongs_to :user
end

我想在目标控制器中创建所有类型的目标,并进行设置,以便localhostL:3000 / waters / new将成为我的“水目标类型”创建页面。 我在正确设置它时遇到了麻烦,因此无法自动设置描述(我的STI列),因为我也想通过我的用户来构建它(因此也设置了user_id)。

我的目标控制器当前看起来像这样...

def create
   @goal =  current_user.goals.build
   ???? code to set goal.description = subtype that the request is coming from

   respond_to do |format|
      if @goal.save
        format.html { redirect_to @goal, notice: 'Goal was successfully created.' }
        format.json { render action: 'show', status: :created, location: @goal }
      else
        format.html { render action: 'new' }
        format.json { render json: @goal.errors, status: :unprocessable_entity }
      end
    end
end

我对Rails很陌生,所以有点困惑。 也使用Rails 4.0

在这种情况下,您需要以某种方式将要创建的类型传达给控制器。

通过在表单中​​包含一个具有您要创建的类型的值的隐藏字段,可以最轻松地建立该字段。

假设表单的块变量为f

<%= f.hidden_field :type, :value => "Excercise" %>

然后,您可以建立一个这样的目标:

current_user.goals.build(type: params[:type])

您可以轻松地看到这是多么危险,在使用用户提交的数据时应始终加倍小心。

为了防范恶意用户,您可以在控制器中设置一个常量

AcceptedModels = ["Excercise", "Yoga", "Water"]

def accepted_type
  (AcceptedModels & params[:type]).first
end

如果您还想隐藏内部结构,则可以使用哈希并发送任何标识符

AcceptedModels = {"0": "Excercise", "1": "Yoga", "2": "Water"}

def accepted_type
  AcceptedModels.fetch(params[:type], nil)
end

无论哪种情况,您都可以像这样建立目标:

current_user.goals.build(type: accepted_type)

最大的缺点是,每次添加/删除更多目标时,您都必须保持AcceptedModels更新

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM