Search code examples
ruby-on-railspathscopes

Rails 4 - scopes - form of expression


I am trying to make an app in Rails 4.

I have models for user, profile and project.

The associations are:

User has_one :profile
Profile belongs_to :user & has_many :projects
Projects belongs_to :profile.

In my profile show page, I am trying to show the projects that belong to the profile.

I have tried to write a scope in my project model as:

scope :by_profile, lambda { | profile_id | where(:profile_id => profile_id) }

Then, in my profile show page, I have tried to use that scope as:

<% Project.by_profile.sort_by(&:created_at).in_groups_of(3) do |group| %>
                        <div class="row">
                            <% group.compact.each do |project| %>
                            <div class="col-md-4">
                                <div class="indexdisplay">
                                    <%= image_tag project.hero_image_url, width: '80px', height: '80px' if project.hero_image.present? %>
                                    <br><span class="indexheading"> <%= link_to project.title, project %> </span>
                                </div>
                            </div>
                            <% end %>
                    <% end %>        
                        </div>

I'm new to scopes and still trying to get a grip on how things work. I'm slightly surprised that if i replace 'by_profile' with 'all' it does actually show an array of projects (I think every project, rather than just those created by the profile id for the relevant profile page).

Does anyone know how to write scopes? Is there something I'm supposed to do in the profiles controller to help make this work?


Solution

  • What you do here

    Project.by_profile..
    

    is not working because you have defined the scope by_profile with arity of one (it should get the proffile_id), but you do not pass any.

    Project.by_profile(params[:profile_id]).sort_by(&:created_at).in_groups_of(3) # will work
    

    But easier here would be just to use the associations:

    Profile.find(params[:id]).projects.sort_by(&:created_at).in_groups_of(3)..
    

    What you should know about scopes? They are pretty much "class" methods, but written in a nicer way :)

    When you call a scope make sure that you pass right amount of arguments to it.

    Here is a shorter way to define your scope (-> is called stubby lambda):

    scope :by_profile, ->(profile_id) { where(profile_id: profile_id) }