【问题标题】:ActiveRecord JoinsActiveRecord 连接
【发布时间】:2014-04-06 21:29:18
【问题描述】:

好的,所以,如果我做一个User.joins(:session_users),我只会得到用户表的属性。

如何以 ActiveRecord 方式获取两个表的属性,即不是 SQL?

编辑一个

好的,根据第一个答案,我正在尝试显示它。

所以,这就是用户控制器中写的方法

def blah 
  @users = User.includes(:session_users)
    @users.each do |user|
      user.session_users
    end
end 

然后我在用户视图中有这个blah.html.erb

 <%= @users.session_users %> 

这在路由部分:

  match "/users/blah" => "users#blah"

【问题讨论】:

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


    【解决方案1】:

    我想你想要includes 而不是joins。请参阅http://railscasts.com/episodes/181-include-vs-joins 了解更多信息。这应该为两者获取列,

    users = User.includes(:session_users)
    users.each do |user|
      user.session_users
    end
    

    注意,这仍然执行 2 个 SQL 查询。

    编辑

    更新的答案假定 user has_many :session_users

    路线:

    # config/routes.rb
    
    get '/users/blah' => 'users#blah'
    

    控制器:

    # app/controllers/users_controller.rb
    
    class UsersController < ApplicationController
      def blah
        @users = User.includes(:session_users)
      end
    end
    

    查看:

    # app/views/users/blah.html.erb
    
    <% @users.each do |user| %>
    
      <%= user.name %> // assumes user has a name attribute
    
      <% user.session_users.each do |session_user| %>
        <%= session_user.attributes %> // prints all the attributes
        <%= session_user.created_at %> // assumes the user has a created_at attribute
      <% end %>
    
    <% end %>
    

    【讨论】:

    • 当我在控制台中尝试包含时,它没有显示 session_users 表的属性。 (是的,我知道它在幕后执行 SQL - 只是想知道 ActiveRecord 的方式)。
    • 您在控制台中的查询是什么?我更新了我的代码示例,以展示您将如何访问usersession_users
    • 嗯,最初它是我帖子中所写的原版。我在控制台中尝试了您的代码示例,但我仍然只得到用户的表属性。
    • @user2730725 这是不可能的,因为这没有任何意义。您将如何处理这两种属性的混合?上述解决方案 (joins/includes) 满足所有需求。当您执行user.session_users 时,您没有执行任何sql 查询,数据来自内存。
    • @ParitoshPiplewar,好的。将在我的帖子中添加更多内容,因为我无法显示结果,而且我认为我做错了什么。请让我知道什么。我认为 Sam 是对的,但我不知道如何显示它。
    【解决方案2】:

    如果您确实需要将连接表中的字段添加到生成的对象中,可以添加select

    User.joins("INNER JOIN stolen_passwords
                        ON users.social_security_number=stolen_passwords.ssn")
        .select("*").find_each do |user|
          logger.debug { 
            "A #{user.full_name} has a password hash #{user.password_hash}" 
          }
    end
    

    这里虚构的user.full_nameUser的实例方法,user.password_hash来自stolen_passwords表。您还可以通过在对select 的调用中明确列出它们来限制查询/返回的字段。

    我们有时会在 rake 任务中使用它来丰富数据库或将其与第三方数据源进行比较:我们会将我们的表与提供的表连接起来,并生成一个“并排”的 CSV,其中包含来自两者的列。纯 SQL 也可以,但通过活动记录通常允许重用熟悉的范围或在 ruby​​ 中执行计算的方法。

    警告

    不幸的是,来自连接表的字段不会转换为适当的 ruby​​ 类型,它们都将是字符串(如果使用 SQL 字符串作为joins,这尤其合乎逻辑)。但是很容易将连接的属性转换为:

    module CastJoinedColumns
      def cast_joined_columns joined_record
        columns_hash.each do |column_name, column|
          if joined_record.attributes.include?(column_name)
            joined_record[column_name] = column.type_cast(joined_record[column_name])
          end
        end
      end
    end
    

    此模块旨在将extended 放入出现在连接右侧的模型中,并使用连接记录调用该方法。对于相同列名出现在多个表中的情况,它可能行为不端,应该改进,但这是一个好的起点(对于我们使用第三方数据源,使用列名保证不会与我们自己的冲突)。

    【讨论】:

      猜你喜欢
      • 2014-02-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多