Rails Joins and include columns from joins table

后端 未结 5 1218
小鲜肉
小鲜肉 2020-12-13 05:01

I don\'t understand how to get the columns I want from rails. I have two models - A User and a Profile. A User :has_many Profile (because users can revert back to an earlier

5条回答
  •  难免孤独
    2020-12-13 05:26

    Use select() to name the columns you want. At least this works in Rails 3.0.9.

    Background: my application has a primary table named :rights. I wanted to be able to ascribe a tag and color to a given :right record so I could easily pick it out of an index listing. This doesn't cleanly fit the Rails picture of associated records; most :rights will never be tagged, and the tags are completely arbitrary (user input via tag/edit).

    I could try duplicating the tag data in the :right record, but that violates normal form. Or I could try querying :tags for each :right record, but that is a painfully inefficient approach. I want to be able to join the tables.

    MySQL console shows:

    mysql> describe rights;
    +------------+---------------+------+-----+---------+----------------+
    | Field      | Type          | Null | Key | Default | Extra          |
    +------------+---------------+------+-----+---------+----------------+
    | id         | int(11)       | NO   | PRI | NULL    | auto_increment |
    
      ...
    
    | Tagid      | int(11)       | YES  |     | NULL    |                |
    +------------+---------------+------+-----+---------+----------------+
    
    mysql> describe tags;
    +------------+--------------+------+-----+---------+----------------+
    | Field      | Type         | Null | Key | Default | Extra          |
    +------------+--------------+------+-----+---------+----------------+
    | id         | int(11)      | NO   | PRI | NULL    | auto_increment |
    | TagName    | varchar(255) | YES  |     | NULL    |                |
    | TagColor   | varchar(255) | YES  |     | NULL    |                |
    | created_at | datetime     | YES  |     | NULL    |                |
    | updated_at | datetime     | YES  |     | NULL    |                |
    +------------+--------------+------+-----+---------+----------------+
    

    I am going to use TagName and TagColor in views/rights/index.html.erb, so I want the rights controller to include those columns in the @rights object it passes to the view. Since not every :right has a :tag, I want to use an outer join:

    @rights = Right.joins("LEFT OUTER JOIN tags ON rights.Tagid = tags.id")
    

    But, as everyone has found, this alone doesn't work: a block reference to TagName produces a server error. However, if I add a select at the end, all is well:

    @rights = Right.joins("LEFT OUTER JOIN tags ON rights.Tagid = tags.id").select("rights.*,tags.TagName as TagName,tags.TagColor as TagColor")
    

    Note added 6/7/13: the select clause does not require aliases - this works too:

    .select("rights.*,tags.TagName,tags.TagColor")
    

    Now I can reference TagName and TagColor in my view:

    <% @rights.each do |right| %>
       > ...
    <% end %>
    

提交回复
热议问题