按类名和ID查找ActiveRecord对象

mad*_*tap 2 ruby ruby-on-rails 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
Run Code Online (Sandbox Code Playgroud)

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

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

有关如何按类名和ID查找ActiveRecord对象的任何建议?或者,有没有更好的方法来做这个不发送参数中的东西?

Nit*_*hin 6

你可能想用

params[:vote][:voteable_type].classify.constantize.find(params[:vote][:voteable_id])
Run Code Online (Sandbox Code Playgroud)

或者也

Object.const_get(params[:vote][:voteable_type]).find(params[:vote][:voteable_id])
Run Code Online (Sandbox Code Playgroud)

还检查

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


spi*_*ann 6

这不是直接回答你的问题,但我想挑战你的设计并提出一个不同的方法:我会vote为两个控制器(posts_controllercomments_controller)添加两个独立的方法,如:

# in posts_controller.rb
def vote
  Post.find(params[:id]).vote
end
Run Code Online (Sandbox Code Playgroud)

我认为这更容易阅读和理解.此外,它允许简单和清晰的restful URL.在你的路上定义这样的路线routes.rb

resources :posts do
  post 'vote', on: :member
end
Run Code Online (Sandbox Code Playgroud)

此外,它还为您提供路径助手,就像vote_post_path(@post)构建可读的URL一样/posts/1/vote.

  • 我肯定会选择这种方法. (2认同)