Rails - has_one belongs_to - 在视图中显示值

Rails - has_one belongs_to - 在视图中显示值

问题描述:

我希望我可以忽略一些愚蠢的东西,并且预先感谢您的帮助,我对rails非常陌生,刚完成Michael Hartl的Rails Tutorial Book,而我在没有脚手架的情况下做事。Rails - has_one belongs_to - 在视图中显示值

每个开支都有一个ExpenseType ...(1 = Meals,2 = Airfare等)。我将费用表中的整数存储为type_id。在我看来,我想显示实际ExpenseType的名称字段的值。

错误的是(和我清楚地看到它为什么失败,没有在费用表中没有expense_id列....但我不知道我错过了什么连接。

SQLite3::SQLException: no such column: expense_types.expense_id: SELECT "expense_types".* FROM "expense_types" WHERE "expense_types"."expense_id" = 14 LIMIT 1 

我想我需要提供一个更明确的外键引用,但我尝试包括在该行没有任何帮助。


模型

class Expense < ActiveRecord::Base 
    attr_accessible :amount, :expense_date, :description, :is_billable, :mileage, 
           :pay_method, :project_id, :type_id 

    belongs_to :project 
    has_one :expense_type 

    validates :expense_date, presence: true 
    validates :type_id, presence: true 
    validates :project_id, presence: true 
    validates :amount, presence: true, numericality: { greater_than: 0 } 

end 

和ExpenseType模型

class ExpenseType < ActiveRecord::Base 
    attr_accessible :name, :active 

    belongs_to :expense 

    validates :name, presence: true 

end 

我控制器

class ExpensesController < ApplicationController 

def index 
    @expense = Expense.new 
    @expense_list = Expense.all 

    # UI options 
    @button_text = 'New' 
    @button_type = 'primary' 

end 

def new 
end 

def create 
    @expense = Expense.new(params[:expense]) 
    @expense_list = Expense.all 

    # UI options 
    @button_text = 'New' 
    @button_type = 'primary' 

    if @expense.save 
    #sign_in @expense 
    flash[:success] = "You have added an expense." 
     redirect_to :back 
    else 
     render 'index' 
    end 

end 

def edit 
    @expense = Expense.find(params[:id]) 
    @expense_list = Expense.all 

    # UI options 
    @button_text = 'Save' 
    @button_type = 'success' 

    render 'index' 
end 

def update 
    @expense = Expense.find(params[:id]) 
    @expense_list = Expense.all 
    if @expense.update_attributes(params[:expense]) 
    flash[:success] = "Updated" 
    #sign_in @expense 
    redirect_to :back 
    else 
    render 'index' 
    end 
end 

def destroy 
    @expense = Expense.find(params[:id]) 
    @expense.destroy 
    flash[:success] = "expense deleted" 
    redirect_to :back 
end 


end 

最后认为

<% provide(:title, 'Expenses') %> 
<h1>Manage Expenses</h1> 

<div class="row"> 
    <div class="span11 well"> 
    <%= form_for @expense do |f| %> 
    <%= render 'shared/error_messages', object: f.object %>  

    <div class="row"> 


      <div class="span4"> 
      <%= f.label :project_id %> 
      <%= f.text_field :project_id, class: "span4" %> 
      </div> 


    </div> 
    <div class="row"> 

      <div class="span2"> 
      <%= f.label :expense_date, "Date" %> 
      <%= f.text_field :expense_date, class: "span2", value: "03/04/2012" %> 
      </div> 


      <div class="span3"> 
      <%= f.label :type_id %> 
      <%= collection_select(:expense, :type_id, ExpenseType.all, 
        :id, :name, { prompt: 'Select Expense Type'}, { class: 'span3' }) %> 
      </div> 

      <div class="span1"> 
      <%= f.label :amount %> 
      <%= f.text_field :amount, class: "span1" %> 
      </div>   

      <div class="span1"> 
      <%= f.label :mileage %> 
      <%= f.text_field :mileage, class: "span1" %> 
      </div> 
      <div class="span1"> 
      <%= f.label :is_billable, "Billable?" %> 
      <%= f.text_field :is_billable, class: "span1" %> 
      </div>       
      <div class="span2"> 
      <%= f.label :pay_method %> 
      <%= f.text_field :pay_method, class: "span2" %> 
      </div>   


    </div> 
    <div class="row"> 
      <div class="span4"> 
      <%= f.label :description %> 
      <%= f.text_area :description, rows: 2, class: "span4" %> 
      </div> 

      <div class="span3"> 
      <%= f.label :description, "Attendees" %> 
      <%= f.text_area :description, rows: 2, class: "span3" %> 
      </div> 
     <div class="span2"> 
      <BR> <%= f.submit " #{@button_text} ", class: "btn btn-large btn-#{@button_type}" %> 
      </div> 

    </div>  
    <% end %> 
    </div> 
</div> 



<div class="row"> 
    <div class="span12"> 
    <table class="table table-bordered table-striped"> 
     <thead> 
     <tr> 
      <th>Date</th> 
      <th>Project</th> 
      <th>Type</th> 
      <th>Amount</th>   
      <th>Description</th> 
     </tr> 
     </thead> 
     <tbody> 
     <% @expense_list.each do |expense_item| %> 

     <tr> 
      <td><%= expense_item.expense_date %></td> 
      <td><%= expense_item.project_id %></td>   
      <td><%= expense_item.type_id %></td>   
      <td><%= expense_item.amount %></td> 
      <td><%= expense_item.description %></td> 

      <td><%= link_to 'Edit', edit_expense_path(expense_item[:id]) %></td> 
      <td><%= link_to 'Delete', expense_item, method: :delete, data: { confirm: 'Are you sure?' } %></td> 
     </tr> 
     <% end %> 
     </tbody> 
    </table> 

    </div> 
</div> 

...我工作的部分是后者的一部分,粘贴这里再次为了清晰起见

<% @expense_list.each do |expense_item| %> 

      ..... 

<%= expense_item.expense_type.name %> 

      ...... 
     <% end %> 

您可以在模型关联中指定FK。 而且,看来你应该在这里使用belongs_to的关系,而不是一个HAS_ONE

HAS_ONE意味着一个变化的消费对象是指费用类型记录也应该改变(不,它有,但按照惯例) 。

如果使用HAS_ONE你需要做的:

has_one :expense_type, primary_key: :type_id 

随着belongs_to的:

belongs_to :expense_type, foreign_key: :type_id 

基于我怎么感觉你的代码应该在ExpenseType结构化你应该有:

has_many :expenses, foreign_key: :type_id 
+0

非常感谢,这是我失踪的一块。我很欣赏关系协会的feedabck!我会投票,但我是一个新手:) – Atari2600 2012-07-22 21:53:47