Rails has_many:通过关联:通过外键检索外部属性

时间:2015-07-01 22:30:53

标签: ruby-on-rails-4 orm foreign-keys foreign-key-relationship jointable

在我们的Rails应用程序中,有3个模型:

class User < ActiveRecord::Base
  has_many :administrations, dependent: :destroy
  has_many :calendars, through: :administrations
end

class Administration < ActiveRecord::Base
  belongs_to :user
  belongs_to :calendar
end

class Calendar < ActiveRecord::Base
  has_many :administrations, dependent: :destroy
  has_many :users, through: :administrations
end

以下是相应的迁移:

class CreateUsers < ActiveRecord::Migration
  def change
    create_table :users do |t|
      t.string :first_name
      t.string :last_name
      t.string :email

      t.timestamps null: false
    end
  end
end

class CreateAdministrations < ActiveRecord::Migration
  def change
    create_table :administrations do |t|
      t.references :user, index: true, foreign_key: true
      t.references :calendar, index: true, foreign_key: true
      t.string :role

      t.timestamps null: false
    end
  end
end

class CreateCalendars < ActiveRecord::Migration
  def change
    create_table :calendars do |t|
      t.string :name

      t.timestamps null: false
    end
  end
end

编辑:这里也是我们的UsersController

class UsersController < ApplicationController
  before_action :logged_in_user, only: [:edit, :update, :destroy]
  before_action :correct_user,   only: [:edit, :update]
  before_action :admin_user,     only: [:index, :destroy]

  def index
    @users = User.paginate(page: params[:page], :per_page => 10)
  end

  def show
    @user = User.find(params[:id])
    @administrations = @user.administrations
    @calendar = current_user.calendars.build if logged_in?
  end

  def new
    @user = User.new
  end

  def create
    @user = User.new(user_params)
    if @user.save
      @user.send_activation_email
      flash[:info] = "Please check your email to activate your account."
      redirect_to root_url
    else
      render 'new'
    end
  end

  def edit
    @user = User.find(params[:id])
  end

  def update
    @user = User.find(params[:id])
    if @user.update_attributes(user_params)
      flash[:success] = "Profile updated"
      redirect_to @user
    else
      render 'edit'
    end
  end

  def destroy
    User.find(params[:id]).destroy
    flash[:success] = "User deleted"
    redirect_to users_url
  end

  private

    def user_params
      params.require(:user).permit(:first_name, :last_name, :email,
                                    :password, :password_confirmation)
    end

    # Before filters

    # Confirms the correct user.
    def correct_user
      @user = User.find(params[:id])
      redirect_to(root_url) unless current_user?(@user)
    end

    # Confirms an admin user.
    def admin_user
      redirect_to(root_url) unless current_user.try(:admin?)
    end

end

一旦用户登录(身份验证系统已经启动并运行),我们希望在他的个人资料(用户#show)上显示他创建的所有日历。

我们已使用以下实例播种数据库:

User.create!(first_name:  "Andy") # This user's id is 1.

Calendar.create!(name: "CalendarA")

Calendar.create!(name: "CalendarB")

Calendar.create!(name: "CalendarC")

Administration.create!(user_id: 1, calendar_id: 1, role: "Creator")

Administration.create!(user_id: 1, calendar_id: 2, role: "Editor")

Administration.create!(user_id: 1, calendar_id: 3, role: "Viewer")

然后,我们创建了一个_administration.html.erb部分:

<li id="administration-<%= administration.id %>">
  <span class="name"><%= administration.calendar_id %></span>
</li>

并将其包含在我们的用户show.html.erb文件中:

<p><%= @user.first_name %>'s calendars</p>
<% if @user.administrations.any? %>
<%= render @administrations %>
<% end %>

这是有效的,我们得到:

  

安迪的日历:

     
      
  • 1
  •   
  • 2
  •   
  • 3
  •   

但是,我们希望为每个用户提供的不仅是他日历的id,还有他们的name,就像这样:

  

安迪的日历:

     
      
  • 1 CalendarA
  •   
  • 2 CalendarB
  •   
  • 3 CalendarC
  •   

所以我们尝试按如下方式更新_administration.html.erb部分:

<li id="administration-<%= administration.id %>">
  <span class="name"><%= administration.calendar_id.name %></span>
</li>

导致以下错误:

NoMethodError in UsersController#show

undefined method `name' for 1:Fixnum

Application Trace | Framework Trace | Full Trace
app/views/administrations/_administration.html.erb:2:in `_app_views_administrations__administration_html_erb__2225316747000531998_70329866860100'
app/views/users/show.html.erb:32:in `_app_views_users_show_html_erb___891585127045041471_70329832995240'

我们如何访问&#34;外国&#34; name模型中的calendar属性通过加入calendar_id模型中的外键administration

1 个答案:

答案 0 :(得分:2)

如果您的关联设置正确,

administration.calendar.name应该有效。

或者,您可以将此方法添加到Administration

def calendar_name
  calendar.name
end

然后只需致电administration.calendar_name