Method each strange behavior with AR association

49 views
Skip to first unread message

Николай Спелый

unread,
Sep 4, 2015, 10:04:58 AM9/4/15
to Ruby on Rails: Talk
Hi.
I write
<%= Chat.find_by(id: 6).chatusers.each { |chat_user| chat_user.user.inspect } %>

(There are three models: Chat, Chatuser, User)

Chat.find_by(id: 6).chatusers returns collection of table "chats_users" and this is fine working.
But i can not get model user by each element of collection in method "each".
So, question is why each not working to get relative model "user" or how to resolve my task by each or another way.

Thanks.


Colin Law

unread,
Sep 4, 2015, 10:24:25 AM9/4/15
to Ruby on Rails: Talk
What error are you getting (copy/paste it from the log please)? Also
copy/paste the section of chat_user.rb showing the associations.

Colin

Николай Спелый

unread,
Sep 4, 2015, 10:32:01 AM9/4/15
to Ruby on Rails: Talk
There are no errors given. Instead rails puts result of Chat.find_by(id: 6).chatusers, not result of "each", that's strange.

class Chatuser < ActiveRecord::Base
  self.table_name = "chats_users"
  belongs_to :chat
  belongs_to :user

  validates :chat_id, presence: true
  validates :user_id, presence: true
end

Colin Law

unread,
Sep 4, 2015, 10:47:10 AM9/4/15
to Ruby on Rails: Talk
On 4 September 2015 at 15:32, Николай Спелый <peavey...@gmail.com> wrote:
> There are no errors given. Instead rails puts result of Chat.find_by(id:
> 6).chatusers, not result of "each", that's strange.

Now I look again that is not surprising. The method inspect outputs
to the server terminal window not to the html for display, if you look
in the server window you should see it. You need to do something like

<% Chat.find_by(id: 6).chatusers.each do |chat_user| %>
<%= chat_user.user.name %>
<% end %>

If you are trying to get debug out then the best way is
<% logger.info Chat.find_by(id: 6).chatusers.each { |chat_user|
chat_user.user.inspect %>
which will appear in development.log. You can also use logger.info in
model or controller.

Colin

>
> class Chatuser < ActiveRecord::Base
> self.table_name = "chats_users"
> belongs_to :chat
> belongs_to :user
>
> validates :chat_id, presence: true
> validates :user_id, presence: true
> end
>
> --
> You received this message because you are subscribed to the Google Groups
> "Ruby on Rails: Talk" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to rubyonrails-ta...@googlegroups.com.
> To post to this group, send email to rubyonra...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/rubyonrails-talk/3ba9d885-0e29-4f76-995e-93c1b949f637%40googlegroups.com.
>
> For more options, visit https://groups.google.com/d/optout.

Николай Спелый

unread,
Sep 4, 2015, 3:56:54 PM9/4/15
to Ruby on Rails: Talk
Great !
I already try write this logic but it not works. But when i copy-paste your variant it's work.
So difference is in formating code, i write in one line, you write in three lines.
That's nice for resolving problem, but why it's works in divided style of ruby and not works in one-line style ?
My one-line is <%= Chat.find_by(id: 6).chatusers.each { |chat_user| chat_user.user } %> which about i told.

Rob Biedenharn

unread,
Sep 4, 2015, 4:27:21 PM9/4/15
to rubyonra...@googlegroups.com
So you have:

<%= something %>

which ERB interprets as call .to_s on the result of evaluating something and add that to the output (possibly after making it HTML-safe depending on your Ruby on Rail version)

Therefore, what is the value of 

Chat.find_by(id: 6).chatusers.each { |chat_user| chat_user.user }

Well, that's just something.each {|…| … } which has the value of something. In your case, the same as if you just had:

Chat.find_by(id: 6).chatusers

This is probably some ActiveRecord proxy for the association. The default .to_s is very likely similar to .inspect and looks something like:

#<ActiveRecord::… >

So plop that into your HTML and a browser sees the <…> as an unknown element and does nothing so you're left with:

#

in your page. Does that make sense to you?

-Rob

tamouse pontiki

unread,
Sep 6, 2015, 9:51:41 AM9/6/15
to rubyonra...@googlegroups.com
On Fri, Sep 4, 2015 at 3:26 PM, Rob Biedenharn <r...@agileconsultingllc.com> wrote:
On 2015-Sep-4, at 15:56 , Николай Спелый <peavey...@gmail.com> wrote:

Great !
I already try write this logic but it not works. But when i copy-paste your variant it's work.
So difference is in formating code, i write in one line, you write in three lines.
That's nice for resolving problem, but why it's works in divided style of ruby and not works in one-line style ?
My one-line is <%= Chat.find_by(id: 6).chatusers.each { |chat_user| chat_user.user } %> which about i told.

The problem is that ruby is swallowing whatever happens inside the .each -- what you want is probably .map instead. The return value from .each is the collection. The return value from map is a new collection of the results of the block.

Try this:

    Chat.find_by(id: 6).chatusers.map{|chat_user| chat_user.user}


Reply all
Reply to author
Forward
0 new messages