【问题标题】:Using a join table's row existence as an alias使用连接表的行存在作为别名
【发布时间】:2018-06-13 14:16:47
【问题描述】:

给定一个名为 Event (id, name) 的模型和一个名为 EventUser (event_id, user_id) 的模型,我遍历事件。在此迭代期间,我会根​​据 EventUser 的存在来显示登录用户是否正在参加活动。标准的东西。

我知道我可以对每个事件执行查询,并且有诸如

之类的东西
class Event < ActiveRecord::Base

  def user_attending?(user)
    event_users.find_by(:user_id => user.id)
  end 

end

但这不是很干净、高性能或可扩展。

我可以从事件列表中加载所有用户参加的事件,例如,

@events = Event.all 
@attending_events = current_user.event_users.where(:event_id => @events.map(&:id))

哪个更好,但不是很好。我可以用这个为我的事件模型添加一个访问器并遍历@attending_events,但这似乎很恶心。

我想在我的理想情况下,我可以在events.id = event_users.event_idevent_users.user_id = current_user.id 上加入两个表,如果该行存在,我可以将/a 结果列标记为@987654326 @

我如何使用 Arel 或 ActiveRecord 甚至 SQL 来做到这一点?在这里使用 PostgreSQL。

【问题讨论】:

    标签: ruby-on-rails postgresql activerecord arel


    【解决方案1】:

    我很困惑。假设:

    • 您已在 User 模型中设置了 has_many :events, through: :event_users
    • 您有一个实例变量(可能在您的控制器中)类似于@user_events = user.events
    • 你有一个实例变量(大概也在你的控制器中)类似于@events = Event.all

    在你看来,是不是有点像(假设erb):

    <% @events do |event| %>
      <% if @user_events.include?(event) %>
        ... do some stuff
      <% else %> 
        ... do some other stuff
      <% end %>
    <% end %>
    

    也许我说得太密集了,完全没有抓住重点……如果是这样,请提前道歉。

    【讨论】:

    • 我认为 OP 想要做的是完全避免将 user_events 加载到另一个查询中,而是向 Events 查询添加一个别名,以指示是否存在基于他提供的条件的匹配行。跨度>
    • 我不确定“向事件查询添加别名”是什么意思。但是,除非这是一个具有高容量或大量记录的生产系统,否则这对我来说似乎有点抢先优化。没有?
    【解决方案2】:

    你想要这样的东西吗?很抱歉猜错了,但如果我没有理解您的问题,您能否更具体一点,您要解决哪个问题?

    class Event < ActiveRecord::Base
      has_many :user_events, class_name: 'UserEvent', inverse_of: :event
      has_many :users, through: :user_events
    end
    

    可能的用途

    1) 建议用法:

    Event.joins(:user_events).where(user_events: {user_id: user.id}).any?

    2)按用户详细信息过滤。请记住,joins 采用事件模型中定义的 has_many 关系,但 where 采用表名。以防has_many 关系名称和表名称不同

    Event.joins(:users).where(users: {name: 'Harry'}).any?

    3) 使用具体记录代替来自Rails - check if record exists in has_many association 的id 的替代用法

    current_event.users.exists?(user.id)

    【讨论】:

      【解决方案3】:

      我想这可能很简单:

      class User < ActiveRecord::Base
        has_many :user_events, class_name: 'UserEvent', inverse_of: :event
        has_many :events, class_name: 'Event'
      end
      

      那你就做 @attending_events = current_user.events

      在您看来,您可以取出您为每个 Event 存储的任何东西,current_user 正在参加。

      【讨论】:

        猜你喜欢
        • 2016-01-28
        • 2013-11-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-05-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多