2015-10-02 102 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