Rails 4 — области видимости — форма выражения

Я пытаюсь сделать приложение в Rails 4.

У меня есть модели для пользователя, профиля и проекта.

Ассоциации таковы:

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

На странице отображения моего профиля я пытаюсь показать проекты, принадлежащие профилю.

Я попытался написать область в моей модели проекта как:

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

Затем на странице моего профиля я попытался использовать эту область как:

<% 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>

Я новичок в прицелах и все еще пытаюсь понять, как все работает. Я немного удивлен, что если я заменю «by_profile» на «все», он действительно покажет массив проектов (я думаю, каждый проект, а не только те, которые созданы идентификатором профиля для соответствующей страницы профиля).

Кто-нибудь знает, как писать области видимости? Есть ли что-то, что я должен сделать в контроллере профилей, чтобы это сработало?


person Mel    schedule 04.02.2016    source источник
comment
почему бы не использовать use Project.where(profile_id: 1)?   -  person Hieu Pham    schedule 04.02.2016


Ответы (1)


Что ты здесь делаешь

Project.by_profile..

не работает, потому что вы определили область действия by_profile с арностью, равной единице (она должна получить proffile_id), но вы ничего не передаете.

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

Но проще здесь было бы просто использовать ассоциации:

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

Что нужно знать о прицелах? Это в значительной степени методы "class", но написанные более красиво :)

Когда вы вызываете область, убедитесь, что вы передаете ей правильное количество аргументов.

Вот более короткий способ определить вашу область видимости (-> называется stubby lambda):

scope :by_profile, ->(profile_id) { where(profile_id: profile_id) }
person Andrey Deineko    schedule 04.02.2016
comment
Привет Андрей, когда я пытаюсь это сделать, я получаю сообщение об ошибке: неправильное количество аргументов (0 вместо 1) - person Mel; 04.02.2016
comment
@user2860931 user2860931 что именно ты пытаешься сделать? - person Andrey Deineko; 04.02.2016
comment
область действия так, как вы написали в конце своего поста: область видимости :by_profile, -›(profile_id) { where(profile_id: profile_id) } - person Mel; 04.02.2016
comment
и как вы его используете? Вы передаете profile_id в Project.by_profile(PROFILE_ID_HERE)? - person Andrey Deineko; 04.02.2016
comment
Я попробовал это так же, как и изначально, а также попробовал: ‹% Project.all.by_profile.sort_by(&:created_at).in_groups_of(3) do |group| %› - person Mel; 04.02.2016
comment
@user2860931 user2860931, как я объяснил, вы ДОЛЖНЫ ПЕРЕДАТЬ profile_id в область действия. В противном случае, как вы ожидаете, что это сузит результат? Project.by_profile(1).sort_by(&:created_at).in_groups_of(3) - person Andrey Deineko; 04.02.2016
comment
но как вы это делаете? - person Mel; 04.02.2016
comment
@ user2860931 вы просто передаете идентификатор :) Project.by_profile(1).sort_by(&:created_at).in_groups_of(3) - person Andrey Deineko; 04.02.2016
comment
так что вы имеете в виду: Project.by_profile(@profile_id).sort_by(&:created_at).in_groups_of(3) - person Mel; 04.02.2016
comment
@ user2860931 это именно то, что я имею в виду, но вместо @profile_id должен быть объект, указывающий на целое число. ПРИМЕР: @profile_id = Profile.first.id. Project.by_profile(@profile_id).sort_by(&:created_at).in_groups_of(3) - person Andrey Deineko; 04.02.2016
comment
Я думал, что именно этого я достиг, написав область видимости. Я не знаю, как выразить идентификатор, чтобы он указывал на идентификатор профиля страницы профиля, на которой отображаются проекты. Я потерялся, как понять это. - person Mel; 04.02.2016
comment
Если я попробую: Project.by_profile(profile_id).sort_by(&:created_at).in_groups_of(3) do |group| %›, я получаю эту ошибку: неопределенная локальная переменная или метод `profile_id’ для #‹#‹Class:0x007f868f7e5050›:0x007f8691e20828› - person Mel; 04.02.2016
comment
@ user2860931, это довольно просто, посмотри: Project.by_profile(params[:profile_id]).sort_by(&:created_at).in_groups_of(3). (или params[:id] в зависимости от URL-адреса) Я не знал, что это проблема. - person Andrey Deineko; 04.02.2016
comment
@ user2860931 ты пробовал? - person Andrey Deineko; 04.02.2016
comment
Сфера не работает (выдает все проекты по всем профилям). Но это работает, если я делаю: Profile.find(params[:id]).projects.sort_by(&:created_at).in_groups_of(3).. - person Mel; 04.02.2016
comment
Объем в данном случае не имеет смысла, потому что он достижим за счет существующих ассоциаций, а объем приводит к легкости. А вообще прицелы очень мощная штука - person Andrey Deineko; 04.02.2016