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

时间:2012-07-22 20:26:10

标签: ruby-on-rails activerecord

我希望我忽略了一些愚蠢的事情,并提前感谢你的帮助,我对rails很新,刚刚完成了Michael Hartl的Rails教程书,我正在努力做一些没有脚手架的事情。

每个费用都有费用类型...(1 =餐,2 =机票等)。我将整数存储在费用表中作为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 %> 

1 个答案:

答案 0 :(得分:0)

您在模型关联中指定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