How to use scopes in rails to query the database for a subset of information and display it

am a beginner and I appreciate an answer to help me understand where my
knowledge gap is:

The app is to display a post. The posts belong to a category
(appetizers,
entrees…) My thought was to use scopes to display all the appetizers
on
the posts in one view and then have the entrees in another view and so
on.

The models:

class Post < ActiveRecord::Base
attr_accessible :body, :category_id, :title

belongs_to :category

scope :appetizers, -> { where(post.category.name => “Appetizers”)}

end

class Category < ActiveRecord::Base
attr_accessible :name

has_many :posts
end

In the view I want to loop through the posts where the category name is
“Appetizers”.

<% @post.appetizers.each do |app| %>

<% end %>
Title Body Category
<%= app.title %> <%= app.body %> <%= app.category.name%>

I am getting an “undefined method” error. I have tried searching for an
example here that explains what is a correct solution. I also tried
creating a method in the Post model like this:

def appetizers_list

@appetizer_list = Post.appetizers.all

end

Then call the method in the view:

<% @appetizer_list.each do |app| %>

<%= app.title %> <%= app.body %> <%= app.category.name%>

Obviously I am confusing what needs to be done after creating the scope
and
how to get the view to “see” it. Or if I need a scope at all and it can
be
done in a more simple way.

So is there a best practices for retrieving subsets of data in rails and
displaying them to the view?

On Apr 29, 2013 5:40 PM, “akkdio” [email protected] wrote:

am a beginner and I appreciate an answer to help me understand where my
knowledge gap is:

The app is to display a post. The posts belong to a category (appetizers,
entrees…) My thought was to use scopes to display all the appetizers
on
the posts in one view and then have the entrees in another view and so
on.
end

class Category < ActiveRecord::Base
attr_accessible :name

has_many :posts
end

In the view I want to loop through the posts where the category name is
“Appetizers”.
<%= app.title %>
<%= app.body %>
<%= app.category.name%>

<% end %>

I am getting an “undefined method” error. I have tried searching for an
example here that explains what is a correct solution. I also tried
creating a method in the Post model like this:

<%= app.title %> <%= app.body %> <%= app.category.name%>

Obviously I am confusing what needs to be done after creating the scope
and how to get the view to “see” it. Or if I need a scope at all and it
can
be done in a more simple way.

So is there a best practices for retrieving subsets of data in rails and
displaying them to the view?

what and where is the reported error?

On 29 April 2013 23:39, akkdio [email protected] wrote:

attr_accessible :body, :category_id, :title

<th>Category</th>

<% @post.appetizers.each do |app| %>

<%= app.title %> <%= app.body %> <%= app.category.name%>

As tamouse suggests it would have been better if you could have told
us the exact error and which line it is on, but if the error is on
this line, and is saying calling method name for nil, then it is
because one of the posts does not have an associated category (so
app.category is nil)

Colin

On Monday, April 29, 2013 6:39:56 PM UTC-4, akkdio wrote:

class Post < ActiveRecord::Base
attr_accessible :name
Body

and how to get the view to “see” it. Or if I need a scope at all and it can
be done in a more simple way.

So is there a best practices for retrieving subsets of data in rails and
displaying them to the view?

Apologies to both Colin and Tamouse. Indeed as Colin surmised the error
is:

 undefined method `each' for nil:NilClass

 Extracted source (around line *#13*):

10:

 11:   </tr>

 12:

  13: <% @appetizers_list.each do |app| %>

   14:   <tr>

   15:     <td><%= app.title %></td>

    16:     <td><%= app.body %></td>

I did try what was suggested in this blog post -
Scopes in Rails which involves
creating a controller action adding a custom route and creating a
link_to
in the view. This worked but at the expense of adding more to the
controller. Here is that solution:

Action in Post Controller:

   def appetizers

  @posts = Post.appetizers

  render 'index'

   end

*Route: *

     get 'posts/appetizers' => 'posts#appetizers', :as =>

‘appetizers_posts’

Change in Post Model:

        scope :appetizers, -> { where(:category_id => 3)}

And change in the view to be a link:

     <% @posts.each do |post| %>

    <tr>

       <td><%= post.title %></td>

       <td><%= post.body %></td>

       <td><%= post.category.name%></td>

     </tr>

    <% end %>

    <%= link_to 'Appetizers', appetizers_posts_path %>

So this works but it seems like it is not the best way to do it - seems
like the controller would get bloated if there are a lot of categories.
Another issue is that in the scope I have to use category_id => 3 to
get
the appetizers to list. I would like at least to have
"post.category.name
=> “Appetizers” so to be more clear about what is being scoped but this
give me an error:

undefined method `key?' for nil:NilClass

I have a feeling there are many ways to display the appetizer listing in
the view. Adding actions to the controller and adding routes seems not
elegant. Can you suggest an alternative and or point to the concept I
seem
to be missing in understanding how to display a subset of information
from
the database in the view. I would like to use scopes and perhaps a
method
in the model…

Again, sorry for not posting the error, I appreciate any comments you
can
give on the subject.

On Tuesday, April 30, 2013 12:45:54 PM UTC+1, akkdio wrote:

So this works but it seems like it is not the best way to do it - seems
like the controller would get bloated if there are a lot of categories.
Another issue is that in the scope I have to use category_id => 3 to get
the appetizers to list. I would like at least to have "post.category.name=>
“Appetizers” so to be more clear about what is being scoped but this
give me an error:

undefined method `key?' for nil:NilClass

Rails doesn’t understand that post.category.name in the where clause
(not
in relation to a specific post) means to add a condition on the
category’s
name. You’d have to do something like

scope :appetizers, -> {joins(:category).where(:categories => {:name 

=>
‘Appetizers’})}

I have a feeling there are many ways to display the appetizer listing in
the view. Adding actions to the controller and adding routes seems not
elegant. Can you suggest an alternative and or point to the concept I seem
to be missing in understanding how to display a subset of information from
the database in the view. I would like to use scopes and perhaps a method
in the model…

I’d suggest adding a single route/action for displaying the posts from
any
category. You can still make it look pretty by setting up slugs for
categories and fetching categories by slug rather than id (friendly_id
is
one of many gems that do this).

You might also consider doing something like this, instead of using
scopes
(assuming you have this by category action)

@posts = Category.find(params[:category_id]).posts

Fred

On Monday, April 29, 2013 6:39:56 PM UTC-4, akkdio wrote:

class Post < ActiveRecord::Base
attr_accessible :name

Body

and how to get the view to “see” it. Or if I need a scope at all and it can
be done in a more simple way.

So is there a best practices for retrieving subsets of data in rails and
displaying them to the view?

Thank you Fred.

This worked great:

    Rails doesn't understand that post.category.name in the where

clause (not in relation to a specific post) means to add a condition on
the
category’s name. You’d have to do

    something like

     scope :appetizers, -> {joins(:category).where(:categories =>

{:name => ‘Appetizers’})}

I understand it a little but will have to learn more about why it works.

I would like to do this:

       I'd suggest adding a single route/action for displaying the

posts from any category.

I will do some reading to see how I need to set it up as I think it
would
help me avoid creating a new route for each category.

I took a gander at friendly_id and it look interesting however, I want
to
get the basics down before I make it pretty…

I tried playing around with this idea:

    @posts = Category.find(params[:category_id]).posts

I think what you mean is to create a method in the Post controller that
will return a list of a specific category. How would I call the method
in
the view so that the it picks up the category_id. I have done the
following:

In the Post controller:

   def category_show
  @posts = Category.find(params[:category_id]).posts
   render 'index'

    end

in the route.rb

      get 'posts/category_show' => 'posts#category_show', :as =>

‘category_show’

In the view: (THIS IS WRONG)

       <% @posts.each do |post| %>
         <tr>
           <td><%= post.title %></td>
           <td><%= post.body %></td>
           <td><%= post.category.name%></td>
           <td><%= link_to 'category_show', category_show_path 

%>

         </tr>
         <% end %>

This results in a error:

  Couldn't find Category without an ID

Fred - thank you for getting me this far. Any comments on the above
would
be appreciated.