2015-10-02 64 views
1

我想在Rails 4中創建一個應用程序。Rails - 如何顯示相關模型的屬性

我剛問過這個相關的問題,並得到了明確的答案。我似乎無法理解如何採取這一邏輯並將其應用於其他地方。

Rails How to show attributes from a parent object

我有一個用戶模型,輪廓模型項目模型和模型的大學。

關聯是:

Profile belongs to university 
Profile belongs to user 
University has many profiles 
University has many projects 
Projects HABTM user 
Projects belong to universities 

在我的項目控制,我定義@creator如下:

def create 
    logger.debug "xxx create project" 
    #authorise @project 
    @project = Project.new(project_params) 
    @project.creator_id = current_user.id 
    @project.users << current_user 
    respond_to do |format| 
     if @project.save 

     format.html { redirect_to @project } 
     format.json { render action: 'show', status: :created, location: @project } 
     else 
     format.html { render action: 'new' } 
     format.json { render json: @project.errors, status: :unprocessable_entity } 
     end 
    end 
    end 

我嘗試定義creator_profile這樣的:

def show 
    #authorise @project 

    @project = Project.find(params[:id]) 
    @creator = User.find(@project.creator_id) 
    @creator_profile = @creator.profile 

    end 

在我單表,我有屬性稱爲標誌和名稱。我使用的是頭像上傳器,其中我定義了徽標(這就是爲什麼我有兩個.logo的原因)。

在我的項目中,show,我想顯示項目創建者所屬的大學。

我已經試過這樣:

<%= image_tag(@creator_profile.university.logo.logo) %> 
     <div class="generaltext"><%= @creator_profile.university.name %> </div> 

我得到這樣的結果:未定義的方法`標誌」的零:NilClass

基於鏈接到我的問題上面

<%= image_tag(creator_profile.university.logo.logo) %> 
      <div class="generaltext"><%= creator_profile.university.name %> </div> 

上我得到這個結果:

undefined local variable or method `creator_profile' for #<#<Class:0x007f998f17ad88>:0x007f998d1ce318> 

我不確定我是否理解上一個問題答案中給出的非常詳細的解釋。如果第一個版本是正確的,那麼我完全不理解這個解釋。如果第二個版本是正確的,那麼爲什麼這個錯誤信息會出現?

林想知道問題出現在那裏沒有大學和用戶之間的關聯嗎?我希望根據創建該項目的用戶來找到創建者所屬的uni。

這就是爲什麼我想:

<%= image_tag(creator_profile.project.university.logo.logo) %> 
       <div class="generaltext"><%= creator_profile.project.university.name %> </div> 

我得到這個錯誤:

undefined method `project' for #<Profile:0x007f998ada41b8> 
+0

在你的控制,我看到您已經定義項目,但我沒有看到你正在定義creator_profile的位置。一旦您在控制器中定義了creator_profile,您就可以訪問它。如果您想要顯示creator_profile的大學,在定義它之後,您應該可以通過creator_profile.university訪問它。 –

+0

我添加了我的控制器show def,這是我試圖定義creator_profile的地方。那已經存在了,所以肯定還有其他問題(或者可能像這樣定義是不正確的)。 – Mel

+0

作爲一個說明,你應該包括你的完整模型構造(IE顯示'belongs_to'等 - 它更容易消化) –

回答

0

It seems I can't understand how to take that logic and apply it elsewhere.

我不認爲你會明白ActiveRecord協會如何在Rails中工作。我會在頁面上進一步解釋。


協會將是問題的可能原因。

設置複雜的關聯總是很棘手 - 最好保持數據儘可能單獨。

這裏是如何我構建模型/協會:

#app/models/university_student.rb 
class UniversityStudent < ActiveRecord::Base 
    belongs_to :university 
    belongs_to :student, class_name: "User" #-> student_id 
end 

#app/models/user.rb 
class User < ActiveRecord::Base 
    has_many :placements, class_name: "UniversityStudent", foreign_key: :student_id #-> user.placements 
    has_many :universities, through: :placements #-> user.universities 

    has_and_belongs_to_many :projects #-> user.projects 

    has_one :profile #-> user.profile (avatar etc) 

    has_many :created_projects, class_name: "Project", foreign_key: :creator_id 
end 

#app/models/profile.rb 
class Profile < ActiveRecord::Base 
    belongs_to :user #-> store avatar here. This can be used across entire app 
end 

#app/models/university.rb 
class University < ActiveRecord::Base 
    has_many :projects 
    has_many :students, class_name: "UniversityStudent" #-> university.students 
end 

#app/models/project.rb 
class Project < ActiveRecord::Base 
    belongs_to :university 
    belongs_to :creator, class_name: "User" #-> creator_id 

    has_and_belongs_to_many :users 

    delegate :profile, to: :creator, prefix: true #-> @project.creator_profile 
end 

這可以讓你做到以下幾點:

def create 
    @project = curent_user.created_projects.new project_params 
    @project.users << current_user 

因爲實際上協會副的數據,你會能夠做到以下幾點:

def show 
    @project = Project.find params[:id] 
    #@creator_profile = @project.creator.profile 
    @creator_profile = @project.creator_profile #-> if you use the delegate method outlined in the models 
end 

-

In my projects, show, I want to display the university that the project creator belongs to.

#app/controllers/projects_controller.rb 
class ProjectsController < ApplicationController 
    def show 
     #@project = Project.find params[:id] 
     @project = current_user.created_projects.find params[:id] 
    end 
end 

#app/views/projects/show.html.erb 
<%= @project.creator.universities.first %> 

上面我的代碼允許多個大學。考慮一下,它應該只限於一個,但我現在將保留它,也許稍後再更改它。

In my uni table, I have attributes called logo and name. I use avatar uploader in which i have logo defined (that's why I have two .logo below).

不要使用兩個logo方法,它是一個反模式(下文解釋)


此解決方法是兩方面:

首先,確保你打電話@creator_profile.university與以下內容:

<%= @creator_profile.university %> 

如果這個工作,這意味着你有.logo.logo(下面詳細介紹)存在問題,如果沒有,則表示您尚未正確定義@creator_profileuniversity關聯。

其次,你需要確保你有正確的控制器/視圖設置。

很多人 - 特別是初學者 - 的問題是他們根本不理解Rails與控制器&視圖一起工作的方式。你需要明白,每次渲染視圖中,僅數據其訪問的是,你在相應的controller動作定義...

#app/controllers/projects_controller.rb 
class ProjectsController < ApplicationController 
    def show 
     @project = Project.find params[:id] 
     @creator_profile = @project.creator_profile 
    end 
end 

#app/views/projects/show.html.erb 
<%= content_tag :div, @creator_profile.universities.first.name, class: "generaltext" %> 

瑣事

  1. @project.creator_id = current_user.id

該守ld不必定義。

你應該能夠改變foreign_key在聯想,讓Rails會自動地定義爲creator_id你:

#app/models/project.rb 
class Project < ActiveRecord::Base 
    belongs_to :creator, class: "User" #-> foreign_key should be :creator_id 
end 

#app/controllers/projects_controller.rb 
class ProjectsController < ApplicationController 
    def create 
     @project = current_user.created_projects.new project_params #-> populates foreign key automatically. 

-

  • .logo.logo
  • 這是一個antipattern

    調用相同的方法兩次只是不好的做法 - 爲什麼你這樣做?

    您可能想要委派您嘗試訪問的任何recursive data(例如上面的.creator_profile的示例),或者您希望重新構建該功能。

    你想以下幾點:

    如果你有委派的資產模型,你可以用下面的閃避:

    <%= @creator_profile.university.images.logo %> 
    
    +0

    謝謝。這是無益的。有很多閱讀材料可以讓我完全理解它,但是你已經指出了我需要去的方向。我有一個使用載波的頭像上傳模型。我在所謂的'logo'中有一個術語,它將圖像大小調整爲logo大小。我將更改模型屬性名稱,以免它們發生衝突。至於其餘的,我正在通過你的意見,並努力學習,因爲我去。非常感謝 - 我更清楚我需要關注什麼才能解決這個問題。 – Mel

    1

    我認爲你需要了解Ruby和Ruby和Rails的一些基本概念,以自己解決這個問題。

    在ruby中,帶有@的變量是實例變量,可在全班使用。這意味着,如果您在控制器中聲明它們,它們將在您的視圖中可用。

    EG @creator_profile = @profile.user

    在另一方面,乏沒有@只在同一區塊內可用。

    一個例子:

    #controller 
    @users = User.all #@users, instance variable 
    
    #view 
    <% @users.each do |user| %> 
        <h3><%= user.name %></h3> #user, local variable. This will work 
    <% end %> 
    <h3><%= user.name %></h3> #this won't work because it is outside the block 
    

    谷歌關於Ruby VAR和範圍。如果你沒有聲明一個實例var,它就不會存在。我認爲你太過於依賴'rails magic'(或者你跳過一些代碼行),如果你沒有聲明一個實例var,它將不存在。命名約定不適用於這種方式。

    最後但不是至少,看看你的關係,我認爲他們需要一些重構。單數和複數的使用也是不正確的。我知道這不是真正的代碼,但它表示它們不反映實體之間的真實關係。

    不要試圖製造'章魚'模型,每個人都屬於每個人,並且思考關係本身,不僅要嘗試關聯模型。 EG:

    Profile 
    belongs_to :creator, class_name: 'User' 
    

    這種方式,你可以這樣寫:

    #controller 
    @profile_creator = Profile.find(params[:id]).creator 
    
    #view 
    @profile_creator.university 
    

    你會更好地瞭解你在做什麼。

    希望它有幫助。

    +0

    謝謝。其中一些對我來說很有意義(而且比我的任何一本書都更加清晰)。但是,你最終的建議讓我感到困惑。在我的項目控制器中,我已經有了@creator_profile(定義如上),當我嘗試顯示屬於創建項目用戶的用戶模型中存儲的屬性時,它就起作用。我可以編寫<%=「#{@creator_profile.title} #{@creator.first_name}#{@ creator.last_name}」%>,它可以在項目視圖中工作。如果我按照您的建議在項目控制器中添加另一個定義,是否打算捕獲當前定義不可用的位? – Mel