Rails 3.2 - 在创建时更新属性 - 我被卡住了

时间:2013-04-25 15:25:33

标签: ruby-on-rails ruby-on-rails-3.2

尝试创建“奖励”记录。我有2个选择框,调用Employee模型来填充奖项中的Nominator和Nominee。

每晚通过批处理作业删除并重新创建Employee表,因此我需要在创建奖项时捕获Nominator和Nominee的所有元数据属性(first_name,last_name等)。

通常情况下,我只会在奖励模型中有一个employee_id外键,然后动态调用员工属性,但每晚都会删除员工数据,所以我完全坚持如何做到这一点的逻辑。请帮忙!并提前感谢!

class AwardsController < ApplicationController
def create
    @award = Award.new(params[:award])

    respond_to do |format|
      if @award.save
        format.html { redirect_to new_award_path, notice: 'Award was successfully created.' }
        format.json { render json: @award, status: :created, location: @award }
      else
        format.html { render action: "new" }
        format.json { render json: @award.errors, status: :unprocessable_entity }
      end
    end
  end
end

-

<%= form_for(@award) do |f| %>
  <% if @award.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@award.errors.count, "error") %> prohibited this award from being saved:</h2>

      <ul>
      <% @award.errors.full_messages.each do |msg| %>
        <li><%= msg %></li>
      <% end %>
      </ul>
    </div>
  <% end %> 
<h4>I am...</h4>
  <label>Name</label>
    <%= f.collection_select :nominator_username, Employee.active.order(:last_name), :username, :lastfirst, :include_blank => true %>


<hr>
<h4>I would like to nominate...</h4>
    <label>Name</label>
    <%= f.collection_select :nominee_username, Employee.active.order(:last_name), :username, :lastfirst, :include_blank => true %>


    <h4>For providing the following...</h4>
    <%= f.text_area :award_description, :size => "50x7" %>

    <button type="submit">Submit</button>
    <div class="spacer"></div><p>

<% end %>

-

class CreateAwards < ActiveRecord::Migration
  def change
    create_table :awards do |t|
        t.string    :nominator_first_name
        t.string    :nominator_last_name
        t.string    :nominator_username
        t.string    :nominator_phone
        t.string    :nominator_employee_number
        t.string    :nominator_mail_station
        t.string    :nominee_first_name
        t.string    :nominee_last_name
        t.string    :nominee_username
        t.string    :nominee_employee_number
        t.string    :nominee_phone
        t.string    :nominee_mail_station
        t.text      :award_description
        t.timestamps
    end
  end
end

更新

好的,我创建了一个rake任务:

#\lib\tasks\import.rake
require 'csv'

desc "Import employees from csv file"
task :import => [:environment] do

  file = "db/users.csv"

  CSV.foreach(file, :headers => true) do |row|
    Employee.find_or_create_by_username({
      :username => row[0],
      :last_name => row[1],
      :first_name => row[2],
      :employee_number => row[3],
      :phone => row[4],
      :mail_station => row[5]
    }
    )
  end
end

当我运行rake import.rake时,我得到:

*Don't know how to build task 'import.rake'*

/.rvm/gems/ruby-1.9.3-p286/gems/rake-10.0.4/lib/rake/task_manager.rb:49:in `[]'
/.rvm/gems/ruby-1.9.3-p286/gems/rake-10.0.4/lib/rake/application.rb:142:in `invoke_task'
/.rvm/gems/ruby-1.9.3-p286/gems/rake-10.0.4/lib/rake/application.rb:101:in `block (2 levels) in top_level'
/.rvm/gems/ruby-1.9.3-p286/gems/rake-10.0.4/lib/rake/application.rb:101:in `each'
/.rvm/gems/ruby-1.9.3-p286/gems/rake-10.0.4/lib/rake/application.rb:101:in `block in top_level'
/.rvm/gems/ruby-1.9.3-p286/gems/rake-10.0.4/lib/rake/application.rb:110:in `run_with_threads'
/.rvm/gems/ruby-1.9.3-p286/gems/rake-10.0.4/lib/rake/application.rb:95:in `top_level'
/.rvm/gems/ruby-1.9.3-p286/gems/rake-10.0.4/lib/rake/application.rb:73:in `block in run'
/.rvm/gems/ruby-1.9.3-p286/gems/rake-10.0.4/lib/rake/application.rb:160:in `standard_exception_handling'
/.rvm/gems/ruby-1.9.3-p286/gems/rake-10.0.4/lib/rake/application.rb:70:in `run'
/.rvm/gems/ruby-1.9.3-p286/gems/rake-10.0.4/bin/rake:33:in `<top (required)>'
/.rvm/gems/ruby-1.9.3-p286/bin/rake:23:in `load'
/.rvm/gems/ruby-1.9.3-p286/bin/rake:23:in `<main>'

更新 - 这是我最后的佣金任务。我在最终的update_column块中收到错误:* nil的未定义方法'update_column':NilClass *

require 'csv'

desc "Import employees from csv file"
task :import => [:environment] do

  file = "db/users1.csv"

    to_be_deactivated = {}
        Employee.all.each do |e|
        to_be_deactivated[ e.employee_number ] = true
    end

  CSV.foreach(file, headers: true) do |row|
    e = Employee.find_or_create_by_employee_number( row[:employee_number] )

    to_be_deactivated[ e.employee_number ] = false

    e.update_attributes(
      :last_name => row[1],
      :first_name => row[2],
      :phone => row[4],
      :mail_station => row[5]) 

    e.save
    end

    to_be_deactivated.each do |n|
        e = Employee.find_by_employee_number( n )
        e.update_column(:active, false)
    end

end

1 个答案:

答案 0 :(得分:1)

如果这是一个Rails应用程序,并且您不仅仅是在遗留数据库上捎带,那么我建议不要完全删除并重新导入employee表,而是运行基于Rails的导入作业,它使用会计员工编号来匹配记录,然后执行find_or_create_by_employee_number - 所以您的Rails ID在整个应用程序中保持不变。

您可以设置Rails来访问多个数据库,然后您可以从会计数据库中读取并将这些记录与Rails应用程序的数据库进行匹配。

如果您无法获得对记帐数据库的直接读取权限,则使用每夜转储,填充临时数据库,您可以在Rails中作为辅助数据库访问该数据库,然后将员工记录与脚本/转轮匹配或者基于rake的脚本,你可以通过cron或延迟工作开始。

这可能是解决这个问题的更简洁方法。

然后,您可以在奖励模型中为员工使用Rails ID。

删除数据库表并每晚重新创建它并不是一个好主意,因为所有引用都变得无用。


如果您不喜欢该建议,则可以使用内部会计员工编号作为奖励模型中的唯一标识符。您不需要存储所有其他属性,因为同一个人的员工编号不会更改 - 只需执行find_by_employee_number


 to_be_deleted = {} # empty Hash
 Employee.all.each do |e|
     to_be_deleted[ e.employee_number ] = true
 end

 # now run your rake task with LDAP import.
 CSV.foreach(file, :headers => true) do |row|
   e = Employee.find_or_create_by_employee_number( row[:employee_number] )

   to_be_deleted[ e.employee_number ] = false

   #... 
   e.update_attributes( ... )
   e.save
 end

 # any records which were not updated by the LDAP import
 # need to be deleted:

 to_be_deleted.each do |n|
    e = Employee.find_by_employee_number( n )
    e.destroy  # also deletes associated records; otherwise use delete
 end