Rails - 如何显示父对象的属性

时间:2015-10-03 05:12:34

标签: ruby-on-rails associations

我正在使用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

这对我来说很奇怪,因为我只是问是否有一个礼物。此外,该代码在关于评论的问题之后出现,并且它似乎没有问题。

这有点令人困惑。

2 个答案:

答案 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 typeImage: Width: 1500 Height: 843 RotatedRect: Center: X: 783.490417 Y: 433.673492 Size: Width: 810.946899 Height: 841.796997 Angle: 95.4092407 列,表示您正在调用的依赖模型(在本例中为“教育者”)。