我正在使用Rails 4制作应用程序。
我试图了解如何使用关联并显示关联模型的属性。我正在努力把握这些概念。
我有一个项目模型和一个project_invitations模型。
协会是:
Projects has many project invitations
Project invitations belong to project
在我的project_invitation节目中,我试图显示项目属性以及项目创建者属性(存储在用户配置文件表中)。
我被卡住了。
在project_invitation show中,我有:
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
在我的项目表中,我有一个名为: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>
我在'title'之前加上'try',因为我在保存新邀请时遇到了其他问题。我想看看这是否是我唯一的问题。我期待下一个错误是同一类型,并用'评论'标记问题。它跳过了那个并引发了一个错误:
undefined method `image' for nil:NilClass
这对我来说很奇怪,因为我只是问是否有一个礼物。此外,该代码在关于评论的问题之后出现,并且它似乎没有问题。
这有点令人困惑。
答案 0 :(得分:0)
.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
答案 1 :(得分:0)
nil的未定义方法`title':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
你可以阅读有关demeter 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
type
,Image:
Width: 1500
Height: 843
RotatedRect:
Center:
X: 783.490417
Y: 433.673492
Size:
Width: 810.946899
Height: 841.796997
Angle: 95.4092407
列,表示您正在调用的依赖模型(在本例中为“教育者”)。