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' ด้วย 'all' มันจะแสดงอาร์เรย์ของโปรเจ็กต์จริง ๆ (ฉันคิดว่าทุกโปรเจ็กต์ ไม่ใช่แค่โปรเจ็กต์ที่สร้างโดย id โปรไฟล์สำหรับหน้าโปรไฟล์ที่เกี่ยวข้อง)

ไม่มีใครรู้วิธีการเขียนขอบเขต? มีบางอย่างที่ฉันควรทำในตัวควบคุมโปรไฟล์เพื่อช่วยในการทำงานนี้หรือไม่


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 ด้วย arity เป็นหนึ่ง (ควรได้รับ 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" ที่ค่อนข้างมาก แต่เขียนด้วยวิธีที่ดีกว่า :)

เมื่อคุณเรียกขอบเขต ตรวจสอบให้แน่ใจว่าคุณส่งอาร์กิวเมนต์ในจำนวนที่ถูกต้อง

นี่เป็นวิธีที่สั้นกว่าในการกำหนดขอบเขตของคุณ (-> เรียกว่าแลมบ์ดาที่มีขนแข็ง):

scope :by_profile, ->(profile_id) { where(profile_id: profile_id) }
person Andrey Deineko    schedule 04.02.2016
comment
สวัสดี Andrey เมื่อฉันลอง ฉันได้รับข้อผิดพลาดที่แจ้งว่า: จำนวนอาร์กิวเมนต์ไม่ถูกต้อง (0 ต่อ 1) - person Mel; 04.02.2016
comment
@ user2860931 คุณลองทำอะไรกันแน่? - person Andrey Deineko; 04.02.2016
comment
ขอบเขตวิธีที่คุณเขียนในตอนท้ายของโพสต์: ขอบเขต :by_profile, -›(profile_id) { โดยที่(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 อย่างที่ฉันอธิบาย คุณต้องผ่าน 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 คุณเพิ่งส่ง ID :) 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