Rails – 如何显示关联模型的属性

我想在Rails 4中创建一个应用程序。

我刚刚问了这个相关的问题并得到了明确的答案。 我似乎无法理解如何采用这种逻辑并将其应用于其他地方。

Rails如何显示父对象的属性

我有一个用户模型,个人资料模型,项目模型和大学模型。

协会是:

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 

在我的uni表中,我有称为徽标和名称的属性。 我使用avatar uploader,其中我定义了徽标(这就是我下面有两个.logo的原因)。

在我的项目中,show,我想展示项目创建者所属的大学。

我试过这个:

  

我得到了这个结果:nil的未定义方法`logo’:NilClass

基于我上面的问题的链接

  

我得到这个结果:

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

我不确定我是否理解上一个问题答案中给出的非常详细的解释。 如果第一个版本是正确的,那么我根本不理解这个解释。 如果第二个版本是正确的,那么为什么会出现此错误消息?

我想知道问题是否出现在大学和用户之间没有关联? 我希望,基于创建项目的用户,找到创建者所属的uni。

这就是我尝试的原因:

  

我收到此错误:

 undefined method `project' for # 

我似乎无法理解如何采用这种逻辑并将其应用于其他地方。

我不认为您了解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 

-

在我的项目中,show,我想展示project creator所属的university

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

我上面的代码允许多个大学。 考虑一下,它应该限于一个,但我现在将它保留原样,也许以后改变它。

在我的uni表中,我有称为徽标和名称的属性。 我使用avatar uploader,其中我定义了徽标(这就是我下面有两个.logo的原因)。

不要使用两种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

这不应该被定义。

您应该能够更改关联中的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. 

-

  1. .logo.logo

这是一个反模式 。

两次调用相同的方法简直就是不好的做法 - 你为什么要这样做?

您要么委托您尝试访问的任何递归数据 (例如上面带有.creator_profile的示例),要么您需要重新.creator_profile该function。

您需要以下内容:

如果您必须委托资产模型,则可以使用以下内容:

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

我认为你需要了解Ruby和Ruby和Rails的一些基本概念来自己解决这个问题。

在ruby中,带有@的变量是实例变量,并且在整个类中都可用。 这意味着如果您在控制器中声明它们,它们将在您的视图中可用。

EG @creator_profile = @profile.user

另一方面,没有@的变量只能在同一个块中使用。

一个例子:

 #controller @users = User.all #@users, instance variable #view <% @users.each do |user| %> 

<%= user.name %>

#user, local variable. This will work <% end %>

<%= user.name %>

#this won't work because it is outside the block

谷歌关于ruby的变种和范围。

另外,我认为你过分依赖’rails magic’(或者你正在跳过一些代码行),如果你没有声明一个实例var,它将不存在。 命名约定不起作用。

最后但并非至少,看看你的关系,我认为他们需要一些重构。 单数和复数的使用也是不正确的。 我知道它不是真正的代码,但它表示它们不反映实体之间的真实关系。

不要试图制作“章鱼”模型,每个人都属于每个人,并考虑关系本身,而不仅仅是试图关联模型。 例如:

 Profile belongs_to :creator, class_name: 'User' 

这样你就可以写:

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

你会更好地理解你在做什么。

希望能帮助到你。