Having trouble with named_scopes for my view

11 views
Skip to first unread message

David Williams

unread,
Mar 9, 2016, 4:53:37 PM3/9/16
to rubyonra...@googlegroups.com
In my articles model, I created a scope that links categories to their
respective articles posts. When I use the rails console, the method
works perfectly when I query the db.

article.rb

scope :category_technology, -> {where(category_id: 1)}

@articles.category_technology
Article Load (0.5ms) SELECT "articles".* FROM "articles" WHERE
"articles"."category_id" = ? ORDER BY "articles"."created_at" DESC
[["category_id", 1]]

Which works.
_________________________________________________________________________

The problem is that I'm unable to use it in the view and iterate over
the records with category_id: 1.

What I'd like to do is something like this
technology_controller.rb

def index
@technology_articles = Article.category_technology.all.limit(10).last
end

_____________________________________________________________________

In the index.html.erb

<% if @technology_articles.present? %>
<% @technology_articles.each do |article| %>
<- omitted ->
<% end %>

I'm getting undefined method `each' for #<Article:0x8300868>

Can you help?

--
Posted via http://www.ruby-forum.com/.

Colin Law

unread,
Mar 9, 2016, 5:16:15 PM3/9/16
to Ruby on Rails: Talk
On 9 March 2016 at 21:51, David Williams <li...@ruby-forum.com> wrote:
> In my articles model, I created a scope that links categories to their
> respective articles posts. When I use the rails console, the method
> works perfectly when I query the db.
>
> article.rb
>
> scope :category_technology, -> {where(category_id: 1)}
>
> @articles.category_technology
> Article Load (0.5ms) SELECT "articles".* FROM "articles" WHERE
> "articles"."category_id" = ? ORDER BY "articles"."created_at" DESC
> [["category_id", 1]]
>
> Which works.

Is that not just the same as @category.articles assuming that @category has id 1

> _________________________________________________________________________
>
> The problem is that I'm unable to use it in the view and iterate over
> the records with category_id: 1.
>
> What I'd like to do is something like this
> technology_controller.rb
>
> def index
> @technology_articles = Article.category_technology.all.limit(10).last

Again, you would be better to do it the other way around, start with
the category and get the articles from that. Note, however that as
you have coded it you have specifed .last which means that
@technology_articles is only one article, not a collection.

> end
>
> _____________________________________________________________________
>
> In the index.html.erb
>
> <% if @technology_articles.present? %>
> <% @technology_articles.each do |article| %>
> <- omitted ->
> <% end %>
>
> I'm getting undefined method `each' for #<Article:0x8300868>

That is because you only have a single Article, not a collection, see above.

Colin

David Williams

unread,
Mar 9, 2016, 5:26:07 PM3/9/16
to rubyonra...@googlegroups.com
Colin Law wrote in post #1182073:
> On 9 March 2016 at 21:51, David Williams <li...@ruby-forum.com> wrote:
>> "articles"."category_id" = ? ORDER BY "articles"."created_at" DESC
>> [["category_id", 1]]
>>
>>
>> I'm getting undefined method `each' for #<Article:0x8300868>
>
> That is because you only have a single Article, not a collection, see
> above.
>
> Colin

Thanks for responding Colin, I didn't realize .last would lead to a
single article being queried. I thought it would give me the last 10
records. I guess DESC being my default named_scope: default_scope -> {
order(created_at: :desc) } should take care of that for me. Thanks.

Colin Law

unread,
Mar 10, 2016, 3:11:58 AM3/10/16
to Ruby on Rails: Talk
The limit(10) gives you the first ten records, but since you have
ordered descending that means you will get the ten with the highest
created_at. Although default_scope sounds like a good idea I have
several times used it only to find that it causes confusion and now
avoid it. Preferring to explicitly specify the order whenever it
matters (via named scopes if appropriate).

Colin

Walter Lee Davis

unread,
Mar 11, 2016, 9:02:40 AM3/11/16
to rubyonra...@googlegroups.com
Part of one of the RailsConf sessions I went to, either last year or the year before, could have been re-titled "default_scope considered harmful". I don't think it's deprecated or anything, but it is definitely something to use sparingly, and with a lot of forethought about what other scopes you may need later. Better to chain scopes, so you call ControllerName.your_scope.latest, rather than adding the "latest" behavior into your default scope. It makes it more declarative. More (duplicated) characters is not really the issue you want to prioritize. Being able to reason about your code in the current bit you are working on is.

Walter

>
> Colin
>
> --
> 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/CAL%3D0gLva0CaJZaRcMJTW%3DH1kBvmkWCmQUzYhcdGJJP8YW-t97Q%40mail.gmail.com.
> For more options, visit https://groups.google.com/d/optout.

David Williams

unread,
Mar 11, 2016, 11:40:23 AM3/11/16
to rubyonra...@googlegroups.com
Walter Davis wrote in post #1182112:
>>>>
> Part of one of the RailsConf sessions I went to, either last year or the
> year before, could have been re-titled "default_scope considered
> harmful". I don't think it's deprecated or anything, but it is
> definitely something to use sparingly, and with a lot of forethought
> about what other scopes you may need later. Better to chain scopes, so
> you call ControllerName.your_scope.latest, rather than adding the
> "latest" behavior into your default scope. It makes it more declarative.
> More (duplicated) characters is not really the issue you want to
> prioritize. Being able to reason about your code in the current bit you
> are working on is.
>
> Walter

Very true. Thank you for your advice.
Reply all
Reply to author
Forward
0 new messages