乔布斯新

时间:2016-08-17 17:19:03

标签: ruby-on-rails ruby database

一点背景:我最近作为一个Rails开发人员得到了一份新工作,这一切都很好和花花公子(我有一个Rails背景),但我遇到了一个问题,我无法理解。我参与的工作涉及接管公司其他人的项目,但从未完成。所以我的膝盖上有一个未完成的CRM应用程序,需要更有经验的开发人员的帮助才能指出我正确的方向。

当我尝试创建新作业时,我收到错误“ ActiveModel :: MissingAttributeError in Jobs#new ”,然后是“无法写入未知属性`opportunity_id '”。

终端的错误是:

Started GET "/jobs/new" for 127.0.0.1 at 2016-08-17 10:07:44 -0700
Processing by JobsController#new as HTML
  Rendered jobs/new.html.erb within layouts/application (2.0ms)
Completed 500 Internal Server Error in 10ms

ActionView::Template::Error (can't write unknown attribute `opportunity_id'):
    1: <% @job[:opportunity_id] = params[:opportunity_id] %>
    2: <% title "New #{@job.opportunity.name} Job"%>
    3:
    4: <%
  app/views/jobs/new.html.erb:1:in `_app_views_jobs_new_html_erb__443350051_40007592'


  Rendered C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/actionpack-4.1.4/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb (1.0ms)
  Rendered C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/actionpack-4.1.4/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb (1.0ms)
  Rendered C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/actionpack-4.1.4/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb within rescues/layout (34.0ms)

错误来自第1行:

<% @job[:opportunity_id] = params[:opportunity_id] %>

更新:添加了作业模型和作业控制器,以及shcema.rb文件中的视图和作业表。

工作模式:

class Job < ActiveRecord::Base
  mount_uploader :file1, AttachmentUploader
  belongs_to :cost_proposal
  has_many :opportunities
end

职位控制员:

class JobsController < ApplicationController
  before_action :set_job, only: [:show, :edit, :update, :destroy]
  skip_load_and_authorize_resource
  # GET /jobs
  # GET /jobs.json
  def index
    @jobs = Job.all
  end

  # GET /jobs/1
  # GET /jobs/1.json
  def show
  end

  # GET /jobs/new
  def new
  end

  # GET /jobs/1/edit
  def edit
  end

  # POST /jobs
  # POST /jobs.json
  def create
    @job = Job.new(job_params)

    respond_to do |format|
      if @job.save
        format.html { redirect_to @job, notice: 'Job was successfully created.' }
        format.json { render :show, status: :created, location: @job }
      else
        format.html { render :new }
        format.json { render json: @job.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /jobs/1
  # PATCH/PUT /jobs/1.json
  def update
    respond_to do |format|
      if @job.update(job_params)
        format.html { redirect_to @job, notice: 'Job was successfully updated.' }
        format.json { render :show, status: :ok, location: @job }
      else
        format.html { render :edit }
        format.json { render json: @job.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /jobs/1
  # DELETE /jobs/1.json
  def destroy
    @job.destroy
    respond_to do |format|
      format.html { redirect_to jobs_url, notice: 'Job was successfully deleted.' }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_job
      @job = Job.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def job_params
      params.require(:job).permit(:opportunity_id, :number, :name, :flight_date, :flight_sub, :camera, :roll, :map_type, :plan_only, :lab_only, :est_hrs_model, :due_date, :edge_job_id, :custom_trans, :comp_inhouse, :delivered_date, :done, :control_in, :control_status, :at_date, :control_results, :control_check, :scan_staff, :scan_date, :scan_check, :comp_staff, :comp_date, :comp_check, :comp_sub, :comp_sub_due_date, :comp_sub_rec, :img_staff, :img_date, :img_check, :edit_staff, :edit_date, :edit_check, :notes, :file1, :file2, :file3, :file4, :file5, :add_files)
    end
end

schema.rb中的作业表:

  create_table "jobs", force: true do |t|
    t.integer  "cost_proposal_id"
    t.string   "number"
    t.string   "name"
    t.date     "flight_date"
    t.string   "flight_sub"
    t.string   "camera"
    t.string   "roll"
    t.string   "map_type"
    t.integer  "plan_only"
    t.integer  "lab_only"
    t.integer  "est_hrs_model"
    t.date     "due_date"
    t.integer  "edge_job_id"
    t.integer  "custom_trans"
    t.integer  "comp_inhouse"
    t.date     "delivered_date"
    t.integer  "done"
    t.date     "control_in"
    t.string   "control_status"
    t.date     "at_date"
    t.string   "control_results"
    t.integer  "control_check"
    t.string   "scan_staff"
    t.date     "scan_date"
    t.integer  "scan_check"
    t.string   "comp_staff"
    t.date     "comp_date"
    t.integer  "comp_check"
    t.string   "comp_sub"
    t.date     "comp_sub_due_date"
    t.integer  "comp_sub_rec"
    t.string   "img_staff"
    t.date     "img_date"
    t.integer  "img_check"
    t.string   "edit_staff"
    t.date     "edit_date"
    t.integer  "edit_check"
    t.text     "notes"
    t.string   "file1"
    t.string   "file2"
    t.string   "file3"
    t.string   "file4"
    t.string   "file5"
    t.string   "add_files"
    t.datetime "created_at"
    t.datetime "updated_at"
    t.integer  "flown"
    t.integer  "cust_trans"
    t.integer  "delivered"
    t.string   "at_staff"
    t.integer  "at_check"
  end

schema.rb的机会表:

  create_table "opportunities", force: true do |t|
    t.integer  "employee_id"
    t.integer  "emp2_id"
    t.integer  "emp3_id"
    t.string   "name"
    t.datetime "prop_date"
    t.integer  "opp_status_id"
    t.string   "delay"
    t.date     "con_signed"
    t.integer  "quote_won_id"
    t.float    "total_cost"
    t.date     "exp_close"
    t.integer  "pri_comp_id"
    t.text     "notes"
    t.datetime "created_at"
    t.datetime "updated_at"
    t.string   "lost"
    t.string   "won"
    t.string   "location"
    t.integer  "pm_id"
  end

作业新视图(发生错误的地方):

<% @job[:opportunity_id] = params[:opportunity_id] %>
<% title "New #{@job.opportunity.name} Job"%>

<% 
@job[:name] = @job.opportunity.name 
@pm = @job.opportunity.pm_id


%>

<br><br>
<%= render 'form' %>

如果您需要项目中的更多文件,请与我们联系。提前谢谢!

3 个答案:

答案 0 :(得分:1)

当您尝试在不存在的模型上设置属性时,会引发ActiveModel::MissingAttributeError。请记住ActiveRecord&#34;自动&#34;通过从数据库中读取模式来创建setter和getter。

最常见的原因是:

  • 错字(例如,db列名为oportunity‌​_id
  • 尚未运行将列添加到架构的迁移
  • 没有迁移添加列

在视图中为模型分配属性也是一个非常糟糕的代码味道。改为在控制器中执行:

class JobsController < ApplicationController
  # ...

  def new
    @job = Job.new do |j|
      if params[:opportunity_id].present?
        j.opportunity_id = params[:opportunity_id]
      end
    end
  end
  # ...
end

答案 1 :(得分:0)

在您的观点的第2行,看起来您期望新工作已经有相关的机会。

 <% title "New #{@job.opportunity.name} Job"%>

如果是这种情况,则作业路线应嵌套在机会下。所以在config/routes.rb

 resources :opportunities do
   resources :jobs
 end

然后,您可以通过http://localhost:3000/opportunities/:id/jobs/new

创建新职位

在你的JobsController中:

 def new
   @opportunity = Opportunity.find(params[:opportunity_id])
   @job = Job.new(opportunity: @opportunity)
   # ...

答案 2 :(得分:0)

因此,当我查看您的两个表定义时,我看到1)工作中没有opportunity_id键,相反,2)机会中没有job_id键。要使has_many :opportunities生效,您需要在商机表中添加job_id字段。这是我的意思的一个非常简化的例子:

def Job < ActiveRecord::Base
  has_many :opportunities
end

def Opportunity < ActiveRecord::Base
end # shown for completeness of answer only

您需要使用迁移将job_id外键添加到opportunity表中,例如:

class AddJobForeignKeyToOpportunities < ActiveRecord::Migration
  def change
    add_column :opportunities, :job_id, :integer
  end
end

如果您不确定如何处理迁移,请查看rails command-line tool的Rails指南。一旦有了这些,Rails将自动为您提供访问与Job相关的机会,如您所料:

job = Job.first
job.opportunities

请注意,由于原始问题中的错误提及,您仍然无法访问job.opportunity_id。您设置的多对一关联要求Opportunity模型具有外键。但是,Rails将允许您访问job.opportunity_ids复数。

[edit]要为工作添加机会,您需要执行以下操作:

opportunity = Opportunity.find(params[:opportunity_id])
job.opportunities << opportunity

您应始终避免直接在关联模型上引用外键。有人在这里的另一个答案或评论中说了这个,但是我找不到它来归功于他们。

而是依赖于Rails提供的方法。在上面的示例中,<<运算符正在有效地设置job_id,以便将它们链接起来。