Rails - 如何显示父对象的属性
Rails - How to show attribute of parent object
我正在用 Rails 4.
开发一个应用
我正在尝试了解如何使用关联以及如何显示关联模型的属性。我正在努力掌握这些概念。
我有一个项目模型和一个project_invitations模型。
协会是:
Projects has many project invitations
Project invitations belong to project
在我的 project_invitation 节目中,我试图显示项目属性以及项目创建者属性(存储在用户配置文件 table 中)。
我卡住了。
在project_invitation节目中,我有:
You're invited to participate in <%= project_invitation.project.title %>
我也试过:
You're invited to participate in <%= @project_invitation.project.title %>
当我尝试 ^^ 我得到这个错误:
undefined method `title' for nil:NilClass
在我的项目 table 中,我有一个名为 :title 的属性。
我希望项目邀请显示显示被邀请者的项目名称。
我尝试这样做的方式有什么问题?
我的 project_invitations 控制器具有以下内容(由脚手架生成):
class ProjectInvitationsController < ApplicationController
before_action :set_project_invitation, only: [:show, :edit, :update, :destroy]
# GET /project_invitations
# GET /project_invitations.json
def index
@project_invitations = ProjectInvitation.all
end
# GET /project_invitations/1
# GET /project_invitations/1.json
def show
end
# GET /project_invitations/new
def new
@project_invitation = ProjectInvitation.new
end
# GET /project_invitations/1/edit
def edit
end
# POST /project_invitations
# POST /project_invitations.json
def create
@project_invitation = ProjectInvitation.new(project_invitation_params)
respond_to do |format|
if @project_invitation.save
format.html { redirect_to @project_invitation, notice: 'Project invitation was successfully created.' }
format.json { render action: 'show', status: :created, location: @project_invitation }
else
format.html { render action: 'new' }
format.json { render json: @project_invitation.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /project_invitations/1
# PATCH/PUT /project_invitations/1.json
def update
respond_to do |format|
if @project_invitation.update(project_invitation_params)
format.html { redirect_to @project_invitation, notice: 'Project invitation was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: @project_invitation.errors, status: :unprocessable_entity }
end
end
end
# DELETE /project_invitations/1
# DELETE /project_invitations/1.json
def destroy
@project_invitation.destroy
respond_to do |format|
format.html { redirect_to project_invitations_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_project_invitation
@project_invitation = ProjectInvitation.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def project_invitation_params
if can? :create, Project,
params[:project_invitation].permit(:comment, :expiry_date, :draft, :course_credit)
elsif can? :read, ProjectInvitation
params[:project_invitation].permit(:student_accepted, :sponsor_accepted)
end
end
end
project_invitation 型号有:
class ProjectInvitation < ActiveRecord::Base
belongs_to :project
belongs_to :user
end
项目模型有:
class Project < ActiveRecord::Base
include RoleModel
#belongs_to :students, through: :courses, counter_cache: true
has_many :project_questions, dependent: :destroy#, through: :projects
accepts_nested_attributes_for :project_questions
has_one :sweep
accepts_nested_attributes_for :sweep
has_one :educator_project_comment
has_many :project_student_eois
belongs_to :educator
has_many :project_invitations
has_one :video
accepts_nested_attributes_for :video
has_one :finalise, through: :sweep
has_many :observations
has_one :approval_request
belongs_to :industry
belongs_to :course
has_and_belongs_to_many :users
belongs_to :creator, class_name: 'User'
has_many :profiles, through: :industry
mount_uploader :hero_image, AvatarUploader
mount_uploader :link_to_video_proposal, VideoUploader
end
在我的 project_invitiatons 展示页面中,我有:
<div class="containerfluid">
<%= render 'static/deviselinks'%>
<div class="row">
<div class="col-md-10 col-md-offset-1">
<h1 class="header-project" style="margin-bottom:10%">You're invited to participate in <%= @project_invitation.project.try(:title) %></h1>
</div>
</div>
<div class="row">
<div class="col-md-6 col-md-offset-1">
<div class="row">
<div class="col-md-12" style="padding:5%">
<div class="invitebody">
<%= @project_invitation.comment %>
</div>
</div>
</div>
<div class="row">
<div class="col-md-8 col-md-offset-2" style="padding:5%">
<div class="invitebody">
If you'd like to participate in this project, reply by <%= @project_invitation.expiry_date.try(:strftime, '%d %B %Y') %>
<br>
<%= render 'rsvp' %>
</div>
</div>
</div>
</div>
<div class="col-md-3 col-md-offset-1" style="padding: 10%">
<div class="row">
<div class="col-md-12">
<% if @creator_profile.image.present? %>
<%= image_tag (@creator_profile.image.profile) %>
<% else %>
<div class="generaltext">Image TBC</div>
<% end %>
</div>
</div>
<div class="row">
<div class="col-md-12">
<%= "#{@creator_profile.title} #{@creator.first_name} #{@creator.last_name}" %>
</div>
</div>
<div class="row">
<div class="col-md-12">
<%= image_tag (@project.hero_image.thumb) %>
</div>
</div>
<div class="row">
<div class="col-md-12">
<%= @project.title %>
</div>
</div>
</div>
</div>
<div class="formminor">
<%= link_to 'Back', project_invitations_path %>
</div>
</div>
我将 'try' 放在 'title' 之前,因为我在保存新邀请时遇到其他问题。我想看看这是不是我唯一的问题。我期待下一个错误是同类错误并用 'comment' 标记问题。它跳过了那个并引发了一个错误:
undefined method `image' for nil:NilClass
这对我来说很奇怪,因为我只是问是否有一件礼物。此外,该代码出现在有关评论的问题之后,那里似乎没有问题。
这有点令人困惑。
您的 .erb 文件中的代码是正确的。该错误表明没有与@project_invitation 关联的项目。我认为问题可能出在您的控制器代码中。您应该在创建操作中将特定项目分配给新 project_invitation。
试试这个代码:
def create
@project = Project.first #Here I use the first project in your database, you should change it to the project you want to associate with.
#For example, if you are creating project invitations in projects#show view, you can use the following instead
#@project = Project.find(params[:id])
@project_invitation = @project.project_invitations.build(project_invitation_params)
respond_to do |format|
if @project_invitation.save
format.html { redirect_to @project_invitation, notice: 'Project invitation was successfully created.' }
format.json { render action: 'show', status: :created, location: @project_invitation }
else
format.html { render action: 'new' }
format.json { render json: @project_invitation.errors, status: :unprocessable_entity }
end
end
end
undefined method `title' for nil:NilClass
这意味着您尝试访问的变量不存在。
Ruby 将 nil
对象视为 NilClass
,因此当您对此类对象调用 方法 时,Ruby 认为您正在尝试调用不存在的方法。问题不在于方法,而在于缺少变量。
协会
这是我希望看到的代码:
#app/models/project.rb
class Project < ActiveRecord::Base
has_many :invitations
end
#app/models/invitation.rb
class Invitation < ActiveRecord::Base
belongs_to :user
belongs_to :project
delegate :title, to: :project, prefix: true #-> prevents "law of demeter"
end
您可以阅读得墨忒耳定律 here。
我知道你的模型是 ProjectInvitations;我有一个规则,就是让您的模型名称尽可能简洁 - 它有助于整个应用程序的清晰度。
这将允许您调用以下内容:
#app/controllers/invitations_controller.rb
class InvitationsController < ApplicationController
def index
@invitations = Invitation.all
end
def new
@invitation = Invitation.new
end
def create
@invitation = Invitation.new invitation_params
@invitation.save
end
def show
@invitation = Invitation.find params[:id]
end
private
def invitation_params
params.require(:invitation).permit(:user,:project)
end
end
观看次数(修复)
因为你没有解释你在调用哪个视图里面的错误变量,我不得不推测:
#app/views/invitations/index.html.erb
<% @invitations.each do |invitation| %>
<%= invitation.project_title %>
<% end %>
#app/views/invitations/show.html.erb
<%= @invitation.project_title %>
关键是要知道您正在调用哪个视图,从而知道您可以使用哪个 @variable
。我的猜测是您试图在未定义的视图中调用 @project_invitations
变量。
型号
顺便说一句,你真的不应该在一个模型中有那么多关联。
你 可以 - 没有规则反对它 - 但这么多规范的问题是你最终会为一个单一目的创建小功能。
最好的系统是 DRY (Don't Repeat Yourself) - 它们一次又一次地重用功能。
例如...
has_one :educator_project_comment
这可以更改为以下内容:
has_many :comments do
def educators
where type = "Educator"
end
end
然后您可以为 Comments
设置一个 STI table setup,一个 type
列表示您正在调用的依赖模型(在本例中为 "Educator" ).
我正在用 Rails 4.
开发一个应用我正在尝试了解如何使用关联以及如何显示关联模型的属性。我正在努力掌握这些概念。
我有一个项目模型和一个project_invitations模型。
协会是:
Projects has many project invitations
Project invitations belong to project
在我的 project_invitation 节目中,我试图显示项目属性以及项目创建者属性(存储在用户配置文件 table 中)。
我卡住了。
在project_invitation节目中,我有:
You're invited to participate in <%= project_invitation.project.title %>
我也试过:
You're invited to participate in <%= @project_invitation.project.title %>
当我尝试 ^^ 我得到这个错误:
undefined method `title' for nil:NilClass
在我的项目 table 中,我有一个名为 :title 的属性。
我希望项目邀请显示显示被邀请者的项目名称。
我尝试这样做的方式有什么问题?
我的 project_invitations 控制器具有以下内容(由脚手架生成):
class ProjectInvitationsController < ApplicationController
before_action :set_project_invitation, only: [:show, :edit, :update, :destroy]
# GET /project_invitations
# GET /project_invitations.json
def index
@project_invitations = ProjectInvitation.all
end
# GET /project_invitations/1
# GET /project_invitations/1.json
def show
end
# GET /project_invitations/new
def new
@project_invitation = ProjectInvitation.new
end
# GET /project_invitations/1/edit
def edit
end
# POST /project_invitations
# POST /project_invitations.json
def create
@project_invitation = ProjectInvitation.new(project_invitation_params)
respond_to do |format|
if @project_invitation.save
format.html { redirect_to @project_invitation, notice: 'Project invitation was successfully created.' }
format.json { render action: 'show', status: :created, location: @project_invitation }
else
format.html { render action: 'new' }
format.json { render json: @project_invitation.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /project_invitations/1
# PATCH/PUT /project_invitations/1.json
def update
respond_to do |format|
if @project_invitation.update(project_invitation_params)
format.html { redirect_to @project_invitation, notice: 'Project invitation was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: @project_invitation.errors, status: :unprocessable_entity }
end
end
end
# DELETE /project_invitations/1
# DELETE /project_invitations/1.json
def destroy
@project_invitation.destroy
respond_to do |format|
format.html { redirect_to project_invitations_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_project_invitation
@project_invitation = ProjectInvitation.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def project_invitation_params
if can? :create, Project,
params[:project_invitation].permit(:comment, :expiry_date, :draft, :course_credit)
elsif can? :read, ProjectInvitation
params[:project_invitation].permit(:student_accepted, :sponsor_accepted)
end
end
end
project_invitation 型号有:
class ProjectInvitation < ActiveRecord::Base
belongs_to :project
belongs_to :user
end
项目模型有:
class Project < ActiveRecord::Base
include RoleModel
#belongs_to :students, through: :courses, counter_cache: true
has_many :project_questions, dependent: :destroy#, through: :projects
accepts_nested_attributes_for :project_questions
has_one :sweep
accepts_nested_attributes_for :sweep
has_one :educator_project_comment
has_many :project_student_eois
belongs_to :educator
has_many :project_invitations
has_one :video
accepts_nested_attributes_for :video
has_one :finalise, through: :sweep
has_many :observations
has_one :approval_request
belongs_to :industry
belongs_to :course
has_and_belongs_to_many :users
belongs_to :creator, class_name: 'User'
has_many :profiles, through: :industry
mount_uploader :hero_image, AvatarUploader
mount_uploader :link_to_video_proposal, VideoUploader
end
在我的 project_invitiatons 展示页面中,我有:
<div class="containerfluid">
<%= render 'static/deviselinks'%>
<div class="row">
<div class="col-md-10 col-md-offset-1">
<h1 class="header-project" style="margin-bottom:10%">You're invited to participate in <%= @project_invitation.project.try(:title) %></h1>
</div>
</div>
<div class="row">
<div class="col-md-6 col-md-offset-1">
<div class="row">
<div class="col-md-12" style="padding:5%">
<div class="invitebody">
<%= @project_invitation.comment %>
</div>
</div>
</div>
<div class="row">
<div class="col-md-8 col-md-offset-2" style="padding:5%">
<div class="invitebody">
If you'd like to participate in this project, reply by <%= @project_invitation.expiry_date.try(:strftime, '%d %B %Y') %>
<br>
<%= render 'rsvp' %>
</div>
</div>
</div>
</div>
<div class="col-md-3 col-md-offset-1" style="padding: 10%">
<div class="row">
<div class="col-md-12">
<% if @creator_profile.image.present? %>
<%= image_tag (@creator_profile.image.profile) %>
<% else %>
<div class="generaltext">Image TBC</div>
<% end %>
</div>
</div>
<div class="row">
<div class="col-md-12">
<%= "#{@creator_profile.title} #{@creator.first_name} #{@creator.last_name}" %>
</div>
</div>
<div class="row">
<div class="col-md-12">
<%= image_tag (@project.hero_image.thumb) %>
</div>
</div>
<div class="row">
<div class="col-md-12">
<%= @project.title %>
</div>
</div>
</div>
</div>
<div class="formminor">
<%= link_to 'Back', project_invitations_path %>
</div>
</div>
我将 'try' 放在 'title' 之前,因为我在保存新邀请时遇到其他问题。我想看看这是不是我唯一的问题。我期待下一个错误是同类错误并用 'comment' 标记问题。它跳过了那个并引发了一个错误:
undefined method `image' for nil:NilClass
这对我来说很奇怪,因为我只是问是否有一件礼物。此外,该代码出现在有关评论的问题之后,那里似乎没有问题。
这有点令人困惑。
您的 .erb 文件中的代码是正确的。该错误表明没有与@project_invitation 关联的项目。我认为问题可能出在您的控制器代码中。您应该在创建操作中将特定项目分配给新 project_invitation。
试试这个代码:
def create
@project = Project.first #Here I use the first project in your database, you should change it to the project you want to associate with.
#For example, if you are creating project invitations in projects#show view, you can use the following instead
#@project = Project.find(params[:id])
@project_invitation = @project.project_invitations.build(project_invitation_params)
respond_to do |format|
if @project_invitation.save
format.html { redirect_to @project_invitation, notice: 'Project invitation was successfully created.' }
format.json { render action: 'show', status: :created, location: @project_invitation }
else
format.html { render action: 'new' }
format.json { render json: @project_invitation.errors, status: :unprocessable_entity }
end
end
end
undefined method `title' for nil:NilClass
这意味着您尝试访问的变量不存在。
Ruby 将 nil
对象视为 NilClass
,因此当您对此类对象调用 方法 时,Ruby 认为您正在尝试调用不存在的方法。问题不在于方法,而在于缺少变量。
协会
这是我希望看到的代码:
#app/models/project.rb
class Project < ActiveRecord::Base
has_many :invitations
end
#app/models/invitation.rb
class Invitation < ActiveRecord::Base
belongs_to :user
belongs_to :project
delegate :title, to: :project, prefix: true #-> prevents "law of demeter"
end
您可以阅读得墨忒耳定律 here。
我知道你的模型是 ProjectInvitations;我有一个规则,就是让您的模型名称尽可能简洁 - 它有助于整个应用程序的清晰度。
这将允许您调用以下内容:
#app/controllers/invitations_controller.rb
class InvitationsController < ApplicationController
def index
@invitations = Invitation.all
end
def new
@invitation = Invitation.new
end
def create
@invitation = Invitation.new invitation_params
@invitation.save
end
def show
@invitation = Invitation.find params[:id]
end
private
def invitation_params
params.require(:invitation).permit(:user,:project)
end
end
观看次数(修复)
因为你没有解释你在调用哪个视图里面的错误变量,我不得不推测:
#app/views/invitations/index.html.erb
<% @invitations.each do |invitation| %>
<%= invitation.project_title %>
<% end %>
#app/views/invitations/show.html.erb
<%= @invitation.project_title %>
关键是要知道您正在调用哪个视图,从而知道您可以使用哪个 @variable
。我的猜测是您试图在未定义的视图中调用 @project_invitations
变量。
型号
顺便说一句,你真的不应该在一个模型中有那么多关联。
你 可以 - 没有规则反对它 - 但这么多规范的问题是你最终会为一个单一目的创建小功能。
最好的系统是 DRY (Don't Repeat Yourself) - 它们一次又一次地重用功能。
例如...
has_one :educator_project_comment
这可以更改为以下内容:
has_many :comments do
def educators
where type = "Educator"
end
end
然后您可以为 Comments
设置一个 STI table setup,一个 type
列表示您正在调用的依赖模型(在本例中为 "Educator" ).