Pregunta

Ok, so, if I do a User.joins(:session_users), I only get the attributes of users table.

How do I get the attributes of both tables in ActiveRecord way, i.e., not SQL?

EDIT ONE

Ok, based on the first answer, I'm trying to have it displayed.

So, this is the method written in Users Controller

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

Then I have this in the users view blah.html.erb

 <%= @users.session_users %> 

And this in the routing section:

  match "/users/blah" => "users#blah"
¿Fue útil?

Solución

I think you want includes instead of joins. See http://railscasts.com/episodes/181-include-vs-joins for more info. This should fetch columns for both,

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

Note, this still performs 2 SQL queries.

Edit

Updated answer assumes that a user has_many :session_users

Routes:

# config/routes.rb

get '/users/blah' => 'users#blah'

Controller:

# app/controllers/users_controller.rb

class UsersController < ApplicationController
  def blah
    @users = User.includes(:session_users)
  end
end

View:

# 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 %>

Otros consejos

If you really need to add fields from a joined table to the yielded objects, you can add 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

Here imaginary user.full_name is an instance method of User and user.password_hash comes from the stolen_passwords table. You could also limit the queried/returned fields by listing them in the call to select explicitly.

We sometimes use this in rake tasks that enrich the database from or compare it against third party data sources: we would join our tables with provided tables and generate a 'side-by-side' CSV with columns from both. Plain SQL would work just as well, but going via active record often allows to reuse familiar scopes, or methods that perform calculations in ruby.

Caveat

Unfortunately the fields coming from the joined tables will not be cast to appropriate ruby types, they will all be strings (which is especially logical if using SQL string for the joins). But it is easy to cast the joined attributes with something like:

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

This module is meant to be extended into a model appearing on the right side of the join and the method be called with a joined record. It might misbehave and should be improved for the cases where the same column name appears in multiple tables, but is an ok starting point (works perfectly for us with third party data sources using column names guaranteed not to clash with our own).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top