按类名和ID查找ActiveRecord对象

时间:2015-04-15 04:47:47

标签: ruby-on-rails ruby rails-activerecord

我与投票,评论和帖子有多态关联,如下所示:

class Vote < ActiveRecord::Base
  belongs_to :voteable, polymorphic: true
end

class Post < ActiveRecord::Base
  has_many :votes, as: :voteable
end

class Comment < ActiveRecord::Base
  has_many :votes, as: :voteable
end

当我点击upvote链接时,我会在参数中发送voteable_typevoteable_id。在投票控制器中,我想使用这两个字符串找到可投票对象,但我发现的唯一解决方案是eval。我认为从参数中评估字符串并不是一个好主意。

class VotesController < ApplicationController
  def find_voteable
    @voteable = eval("#{params[:vote][:voteable_type]}.find(params[:vote][:voteable_id])")
  end
end

有关如何按类名和ID查找ActiveRecord对象的任何建议?或者,是否有一种更好的方法可以做到这一点,而不是在参数中发送东西?

3 个答案:

答案 0 :(得分:6)

您可能想要使用

params[:vote][:voteable_type].classify.constantize.find(params[:vote][:voteable_id])

Object.const_get(params[:vote][:voteable_type]).find(params[:vote][:voteable_id])

同时检查

http://apidock.com/rails/String/constantize

答案 1 :(得分:6)

这不是您的问题的直接答案,但我想挑战您的设计并提出一种不同的方法:我会向两个控制器添加两个独立的vote方法(posts_controller和{{ 1}}),类似于:

comments_controller

我认为这更容易阅读和理解。此外,它允许简单和清晰的restful URL。在# in posts_controller.rb def vote Post.find(params[:id]).vote end

中定义这样的路线
routes.rb

另外,它为您提供了resources :posts do post 'vote', on: :member end 之类的路径助手,可以构建像vote_post_path(@post)这样的可读URL。

答案 2 :(得分:2)

const_get会为你工作吗?

if const_defined? params[:vote][:voteable_type]
  votable = const_get params[:vote][:voteable_type]
  votable.find params[:vote][:voteable_id]
end