Rails - 如何显示关联模型的属性 [英] Rails - how to show attribute of an associated model

查看:28
本文介绍了Rails - 如何显示关联模型的属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在 Rails 4 中制作一个应用程序.

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

Rails 如何显示属性父对象

我有一个用户模型、配置文件模型、一个项目模型和一个大学模型.

关联是:

简介属于大学个人资料属于用户大学有很多简介大学有很多项目项目 HABTM 用户项目属于大学

在我的项目控制器中,我定义@creator 如下:

def 创建logger.debug "xxx 创建项目"#授权@project@project = Project.new(project_params)@project.creator_id = current_user.id@project.users <<当前用户response_to do |格式|如果@project.saveformat.html { redirect_to @project }format.json { 渲染动作:'show',状态::已创建,位置:@project }别的format.html { 渲染动作:'新' }format.json { 渲染 json: @project.errors, 状态: :unprocessable_entity }结尾结尾结尾

我尝试像这样定义 creator_profile:

def 显示#授权@project@project = Project.find(params[:id])@creator = User.find(@project.creator_id)@creator_profile = @creator.profile结尾

在我的 uni 表中,我有名为 logo 和 name 的属性.我使用头像上传器,我在其中定义了徽标(这就是我在下面有两个 .logo 的原因).

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

我已经试过了:

<%= image_tag(@creator_profile.university.logo.logo) %><div class="generaltext"><%= @creator_profile.university.name %>

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

基于上面我的问题的链接

<%= image_tag(creator_profile.university.logo.logo)%><div class="generaltext"><%= creator_profile.university.name %>

我得到这个结果:

未定义的局部变量或方法`creator_profile' for #<#:0x007f998d1ce318>

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

我想知道问题是不是因为大学和用户之间没有关联?我希望根据创建项目的用户,找到创建者所属的大学.

这就是我尝试的原因:

<%= image_tag(creator_profile.project.university.logo.logo)%><div class="generaltext"><%= creator_profile.project.university.name %>

我收到此错误:

#的未定义方法`project'

解决方案

我似乎无法理解如何将这种逻辑应用到其他地方.

我认为您不了解 ActiveRecord 关联在 Rails 中的工作方式.我将在页面下方进一步解释.

<小时>

您的关联可能是导致问题的原因.

设置复杂的关联总是很棘手 - 最好将数据尽可能分开.

以下是我构建模型/关联的方法:

#app/models/university_student.rb类大学学生 <ActiveRecord::Base归属地:大学归属地:学生,班级名称:用户"#->学生卡结尾#app/models/user.rb类用户用户展示位置has_many :universities, 通过: :placements #->用户.大学has_and_belongs_to_many :projects #->用户项目has_one :profile #->user.profile(头像等)has_many :created_projects, class_name: "Project", foreign_key: :creator_id结尾#app/models/profile.rb班级简介ActiveRecord::Base归属地:用户#->在这里存储头像.这可以在整个应用程序中使用结尾#app/models/university.rb类大学<ActiveRecord::Basehas_many :项目has_many :students, class_name: "UniversityStudent" #->大学生结尾#app/models/project.rb班级项目creator_idhas_and_belongs_to_many :用户委托 :profile, to: :creator, prefix: true #->@project.creator_profile结尾

这允许您执行以下操作:

def 创建@project = current_user.created_projects.new project_params@project.users <<当前用户

因为关联实际上关联您的数据,您将能够执行以下操作:

def 显示@project = Project.find params[:id]#@creator_profile = @project.creator.profile@creator_profile = @project.creator_profile #->如果您使用模型中概述的委托方法结尾

--

<块引用>

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

#app/controllers/projects_controller.rb类 ProjectsController <应用控制器高清秀#@project = Project.find params[:id]@project = current_user.created_projects.find params[:id]结尾结尾#app/views/projects/show.html.erb<%= @project.creator.universities.first %>

我上面的代码允许多所大学.想了想,应该是一个,不过暂时就这样吧,以后可能会改吧.

<块引用>

在我的 uni 表中,我有名为 logo 和 name 的属性.我使用头像上传器,其中定义了徽标(这就是为什么我在下面有两个 .logo).

不要使用两个logo方法,这是一种反模式(解释如下)

<小时>

对此的修复有两个方面:

首先,确保您使用以下内容调用 @creator_profile.university:

<%= @creator_profile.university %>

如果这有效,则说明您的 .logo.logo(详见下文)有问题,如果无效,则说明您尚未定义 @creator_profileuniversity 关联正确.

其次,您需要确保拥有正确的控制器/视图设置.

许多人的问题——尤其是初学者——是他们根本不了解 Rails 与控制器和控制器一起工作的方式.意见.您需要意识到,每次渲染视图时,它可以访问的唯一数据是您在相应的controller 操作中定义的数据...

#app/controllers/projects_controller.rb类 ProjectsController <应用控制器高清秀@project = Project.find params[:id]@creator_profile = @project.creator_profile结尾结尾#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班级项目Foreign_key 应该是 :creator_id结尾#app/controllers/projects_controller.rb类 ProjectsController <应用控制器定义创建@project = current_user.created_projects.new project_params #->自动填充外键.

--

  1. .logo.logo

这是一个反模式.

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

您要么想委托您尝试访问的任何递归数据(例如上面带有 .creator_profile 的示例),或者您需要重构该功能.

您需要以下内容:

如果您必须委托给资产模型,您可以通过以下方式逃脱:

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

I am trying to make an app in Rails 4.

I just asked this related question and got a clear answer. It seems I can't understand how to take that logic and apply it elsewhere.

Rails How to show attributes from a parent object

I have a user model, profile model a projects model and a universities model.

Associations are:

Profile belongs to university
Profile belongs to user
University has many profiles
University has many projects
Projects HABTM user
Projects belong to universities

In my projects controller, I define @creator as follows:

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

I try to define creator_profile like this:

def show
    #authorise @project

    @project = Project.find(params[:id])
    @creator = User.find(@project.creator_id)
    @creator_profile = @creator.profile

  end

In my uni table, I have attributes called logo and name. I use avatar uploader in which i have logo defined (that's why I have two .logo below).

In my projects, show, I want to display the university that the project creator belongs to.

I've tried this:

<%= image_tag(@creator_profile.university.logo.logo) %> 
        <div class="generaltext"><%= @creator_profile.university.name %> </div>

I get this result: undefined method `logo' for nil:NilClass

Based on the link to my problem above

<%= image_tag(creator_profile.university.logo.logo) %> 
            <div class="generaltext"><%= creator_profile.university.name %> </div>

I get this result:

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

I'm not sure I understood the very detailed explanations given in the answer to my previous question. If the first version is right, then I don't understand the explanation at all. If the second version is right, then why does this error message come up?

Im wondering if the problem arises out of there not being an association between university and user? I was hoping, based on the user who created the project, to find the uni that the creator belongs to.

That's why i tried:

<%= image_tag(creator_profile.project.university.logo.logo) %> 
                <div class="generaltext"><%= creator_profile.project.university.name %> </div>

I get this error:

undefined method `project' for #<Profile:0x007f998ada41b8>

解决方案

It seems I can't understand how to take that logic and apply it elsewhere.

I don't think you appreciate how ActiveRecord associations work in Rails. I'll explain further down the page.


Your associations will be the likely cause of the problem.

Setting up complicated associations is always tricky - it's best to keep the data as separate as possible.

Here's how I'd construct the models / associations:

#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

This allows you to do the following:

def create
   @project = curent_user.created_projects.new project_params
   @project.users << current_user

Because the associations actually associate your data, you'll be able to do the following:

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

--

In my projects, show, I want to display the university that the project creator belongs to.

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

My code above allows for multiple universities. Thinking about it, it should be limited to one, but I'll leave it as is for now, maybe change it later.

In my uni table, I have attributes called logo and name. I use avatar uploader in which i have logo defined (that's why I have two .logo below).

Don't use two logo method, it's an antipattern (explained below)


The fix for this is two-fold:

Firstly, make sure you're calling @creator_profile.university with the following:

<%= @creator_profile.university %> 

If this works, it means you have a problem with .logo.logo (detailed below), if it doesn't, it means you've not defined @creator_profile or the university association correctly.

Secondly, you need to ensure you have the correct controller/view setup.

The problem for many people - especially beginners - is they simply don't understand the way Rails works with controllers & views. You need to appreciate that each time you render a view, the only data it has access to is that which you define in the corresponding controller action...

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


Trivia

  1. @project.creator_id = current_user.id

This should not have to be defined.

You should be able to change the foreign_key in the association, so that Rails will automagically define the creator_id for you:

#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

This is an antipattern.

Calling the same method twice is simply bad practice - why are you doing it?

You either want to delegate any recursive data you're trying to access (such as the example with .creator_profile above), or you'll want to restructure that functionality.

You want the following:

If you have to delegate to an assets model, you could get away with the following:

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

这篇关于Rails - 如何显示关联模型的属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
其他开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆