我正在尝试在Rails 4中制作应用程序。
我刚刚问了这个相关的问题并得到了明确的答案。我似乎无法理解如何采用这种逻辑并将其应用到其他地方。
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
在我的uni表中,我有称为徽标和名称的属性。我使用avatar uploader,其中我定义了徽标(这就是我下面有两个.logo的原因)。
在我的项目中,show,我想显示项目创建者所属的大学。
我试过这个:
<%= image_tag(@creator_profile.university.logo.logo) %>
<div class="generaltext"><%= @creator_profile.university.name %> </div>
我得到了这个结果:未定义的方法`logo&#39;为零: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 :(得分: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
Google关于ruby vars和范围。
另外,我认为你过分依赖'rails magic'(或者你正在跳过一些代码行),如果你没有声明一个实例var,它将不存在。命名约定不起作用。
最后但并非至少,看看你的关系,我认为他们需要一些重构。单数和复数的使用也是不正确的。我知道这不是真正的代码,但它表示它们不能反映实体之间的真实关系。
不要试图制作“章鱼”模型,每个人都属于每个人,并考虑关系本身,而不仅仅是试图关联模型。 EG:
Profile
belongs_to :creator, class_name: 'User'
这样你可以写:
#controller
@profile_creator = Profile.find(params[:id]).creator
#view
@profile_creator.university
你会更好地理解你在做什么。
希望它有所帮助。
答案 1 :(得分:0)
似乎我无法理解如何采用这种逻辑并将其应用到其他地方。
我不认为您了解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
-
在我的项目中,显示,我想显示
university
所属的project creator
。
#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表中,我有称为徽标和名称的属性。我使用头像上传器,我已经定义了徽标(这就是我下面有两个.logo的原因)。
不要使用两个logo
方法,它是一个反模式(如下所述)
对此的修复是双重的:
首先,请确保使用以下内容致电@creator_profile.university
:
<%= @creator_profile.university %>
如果此方法有效,则表示您对.logo.logo
(详情如下)有疑问,如果不是,则表示您未定义@creator_profile
或university
关联正确。
其次,您需要确保拥有正确的控制器/视图设置。
许多人 - 特别是初学者 - 的问题是他们根本不理解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" %>
<强>琐事强>
@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.
-
.logo.logo
这是antipattern。
两次调用相同的方法只是不良做法 - 你为什么要这样做?
您要么委托您尝试访问的任何recursive data(例如上面带有.creator_profile
的示例),要么您要重新构建该功能。
您需要以下内容:
如果您必须委托资产模型,则可以使用以下内容:
<%= @creator_profile.university.images.logo %>