【问题标题】:Multiple Polymorphic Attributes on one Model一个模型上的多个多态属性
【发布时间】:2014-07-12 02:41:58
【问题描述】:

我一直在创建一个应用程序,它具有几种不同的模型类型,它们充当不同的页面类型。 我目前有一个具有两个多态属性的 Posts 模型:Postable 和 Posterable,它们分别是发布帖子的页面以及每个帖子的作者。
例如,我希望用户能够创作和接收帖子,同时我还希望群组能够通过管理员用户接收帖子和作者。

我的 Post 模型目前如下:

class Post < ActiveRecord::Base
before_create :set_latlong

belongs_to :posterable, polymorphic: true
    belongs_to :postable, polymorphic: true

default_scope -> { order('created_at DESC') }
validates :content, presence: true, length: { maximum: 140 }
validates :posterable_id, presence: true
validates :posterable_type, presence: true

def set_latlong
    self.latitude = posterable.latitude
    self.longitude = posterable.longitude
end

def self.from_users_favourited_by(user)
    favourited_user_ids = "SELECT favourite_id FROM favouriteusers
                                WHERE favourited_id = :user_id"
    where("posterable_id IN (#{favourited_user_ids}) OR posterable_id = :user_id", user_id: user.id)
end

结束

发布方案是:

  create_table "posts", force: true do |t|
t.string   "content"
t.integer  "posterable_id"
t.string   "posterable_type"
t.float    "latitude"
t.float    "longitude"
t.integer  "postable_id"
t.string   "postable_type"
t.datetime "created_at"
t.datetime "updated_at"

结束

我相信这些都是可行的,也允许各种模型在各种模型页面上发布。但是,我不太确定如何实现这一点,Post 控制器如下:

class PostssController < ApplicationController

before_action :authenticate_user!,仅:[:create, :destroy] before_filter :load_posterable

定义新 @post = Post.new(post_params) 结束

定义创建 @posterable = load_posterable @post = @posterable.posts.build(post_params) @post.postable = find_postable 如果@post.save flash[:success] = "帖子已创建!" 重定向到 root_url 别的 @feed_items = [] 渲染'static_pages/home' 结尾 结束

默认销毁 @post = Post.find(params[:id]) 如果@post.present? @post.destroy 结尾 重定向到 root_url 结束

私人

def post_params
    params.require(:post).permit(:content)
end

def load_posterable
  resource, id = request.path.split('/')[1, 2]
  resource_name = resource.singularize.classify
  if resource_name = "user"
    @posterable = current_user
  else 
    @posterable = resource_name.constantize.find(id)
  end
end

def find_postable
  resource, id = request.path.split('/')[1, 2]
  resource_name = resource.singularize.classify
end

结束

我相信完成这项工作的关键是将 load_posterable 和 find_postable 方法中的“资源”分开,这是我从 Railscast 关于多态关联的教程中获得的,但我真的不知道如何在同款?

【问题讨论】:

  • 你做错了。所以错了,我不知道从哪里开始。为什么评论作者是多态的?管理员是用户的子类型。你过于复杂了,在模型中寻找更简单的通用元素并更好地抽象它们。对于用户/管理员,您可能需要查看 STI,但是一个简单的属性就足够了。
  • @MichaelSzyndel 管理员用于特定实例,而不是用户子类,并且添加了 Admin 属性(即,当用户创建组时,他们自动成为该组的管理员)。然后他们可以做的是在用户或群组墙上以他们自己或他们作为管理员的任何群组的身份发布。
  • 那是什么鬼? resource, id = request.path.split('/')[1, 2]。阅读有关 Rails 路由的信息,从未见过有人这样做,这是有充分理由的。
  • @MichaelSzyndel 我相信我是从railscasts.com/episodes/… 那里得到的,对不起,我只是刚接触rails,刚刚找到自己的脚!
  • 天啊,Rails 演员表中的那种东西?简直不敢相信我的眼睛。反正。放弃 Railscasts 并查看 guides.rubyonrails.com。也可以先尝试一些更简单的东西,比如单个多态关联,最后你会更快地学习和理解。在实施方面,我仍然建议接受我的回答。这是装饰器设计模式,它是一个非常好的方法。

标签: ruby-on-rails comments polymorphic-associations


【解决方案1】:

好的,所以您需要一个 Profile 模型,用户/管理员将使用该模型在网站上进行操作。

您应该为用户自动创建并选择它(默认一个),然后为每个组单独一个成为管理员。

配置文件本身不应真正包含任何属性,只需将它们通过关联(如果您愿意,可能是多态的)委托给用户或其他模型。

这样你就有了一个非常干净的界面,Profile 类将成为你模型的一种装饰器。

在控制器级别,您应该有一个类似于 current_usercurrent_profile 方法,该方法将存储/检索会话中的配置文件 ID。

见:http://en.wikipedia.org/wiki/Decorator_pattern

【讨论】:

  • 我已经添加了我的代码,所以希望这能让你更好地了解我在问什么。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-23
  • 1970-01-01
  • 2013-08-27
  • 1970-01-01
  • 1970-01-01
  • 2011-06-11
相关资源
最近更新 更多