新手问题 Rails 无所适从啊

jarorwar · 2013年04月27日 · 最后由 saillee 回复于 2013年05月10日 · 4287 次阅读

最近在搞 ROR,搞了快有一段时间了。但是拿到一个东西还是不知该从那里做起。 如果用 ruby 搞一个 terminate 的小程序,在不考虑代码风格等的情况下,还是很快能搞定的。但是却不知道如何迁移到 rails 上(毕竟命令行只是给 programmer 来用的啊)

求教了~

找点资料看,这个别人没法回答你。太大了,几句话说不清的。

推荐你看看:《Agile Web Development with Rails》抄书笔记 http://ruby-china.org/topics/10478

如果英文没问题,看 Agile Web Development with Rails 最新版原版是最好的起步路线 http://pragprog.com/book/rails4/agile-web-development-with-rails

在北京没办法,如果在杭州的话可以请我喝杯咖啡聊聊如何学习,:)

#3 楼 @Rei 谢谢。我之前看了 台湾那个大牛写的,实战圣经
看完了。不是很仔细,多看吧~

#5 楼 @jarorwar 北京的愿意喝我的咖啡的同志也可以啊~哈哈

我举个简单的例子,各位帮忙分析下,我该如何下手: 最近给前台做一个考勤的东西。这个考勤是从考勤机里面导出来的一个 excel。(不去说考勤机是否提供我做的这个功能,因为这个事情无从知晓)然后前台就去一天天的对每个人的考勤情况,并且记录到一个 excel 表格中(两个 excel 格式完全不一样)然后统计加班的时间,倒休,请假等信息。 现在,她想直接上传那个最原始的 excel 信息(每一行就是一条打卡记录),然后我这边分析这个 excel(因为打卡跟门禁是同一个认证。所以一天可能有很多次打卡信息),取最早的和最晚的打卡时间。记录到第二个 excel 中,以此类推。取每个月的。以及每个人的。现在我是这么做的 :1、定义了一个 Fingerprint model,这个对应的是基础信息里面的一条打卡记录。 2、生成了 Fingerprints_controller ,并在这个类中加入了一个 upload_excel 的 action,此 action 完成 excel 的上传,同时,读取 excel,写入到 mysql 数据库中。

3:、结下来,不知道该怎么搞了~ 问题: 1、我在 controller 中写了好多好多的业务逻辑代码(在 java 中 controller 很少写业务逻辑的),想问这样正常吗? 2、activeRecor 的插入很慢。5000 多条记录大概 10 分钟左右才跑完,不知道是不是我程序有问题。 3、因为要导出的 excel 的实体模型完全跟基础数据不一样,我是否应该再定义一个 Model。 下面是 controller 的文件上传部分代码,求指教:

def upload_excel
   excel = params[:upload]
   puts excel['datafile'].content_type
   file_name = excel['datafile'].original_filename if (excel['datafile'] != '')
   file = excel['datafile'].read()
   file_type = file_name.split(".").last
   if file_type and 'xls' != file_type
     flash[:alert] = '文件类型不正确!只允许传xls扩展类型的文件!'
     redirect_to :action => :upload_view and return

   end

   new_file_name = file_name
   new_file_name_with_type = "#{new_file_name}.#{file_type}"
   excel_root = get_upload_file_path

   if (!Dir.exist?(excel_root))
     Dir.mkdir(excel_root, 777)
   end
   File.open( get_upload_file_path+new_file_name, 'wb') do |f|
     f.write(file)
   end

   flash[:info] = file_name
   workbook = Spreadsheet.open( get_upload_file_path+new_file_name)
   sheet = workbook.worksheets[0]
   puts sheet.count
   if sheet
     sheet.each do |row|
       finger_print = Fingerprint.new
       finger_print.dept_name     = row[0]
       finger_print.employee_name = row[1]
       finger_print.employee_no   = row[2]
       finger_print.fp_time       = row[3]
       finger_print.machine       = row[4]
       finger_print.no            = row[5]
       finger_print.pattern       = row[6]
       finger_print.card_no       = row[7]
       finger_print.file_name     = new_file_name
       finger_print.save
     end
   end
   redirect_to :action => :upload_view and return
 end

下面是 route,不知这样配置是否优雅:

get "fingerprints/upload_view" => "fingerprints#upload_view"
post "fingerprints/upload_excel" => "fingerprints#upload_excel"
resources :fingerprints

这样插入要生成 5000 个对象。

#7 楼 @jarorwar 这个听起来直接在 excel 里面就能完成啊,有什么特别理由一定要用 rails 做么?

#9 楼 @blacktulip excel 肯定是不能完成。或者你就不考虑需求,权当我是练习好吧 ~

前半部分文件上传,可以交给 carrierwave 这样的 gem 解决。

后面插入部分,基本没问题,就是 ActiveRecord 写法可以改进一下:

Fingerprint.create
   :dept_name     => row[0]
   :employee_name => row[1]
   ...

效率问题我现在不用 ActiveRecord 不清楚,10 分钟有点太慢(120ms/record),一般插入应该十几毫秒。改进办法:

  1. 拼装一个大的 SQL 字符串一次插入
  2. 用异步插件(比如 sidekiq)把任务异步处理

controller 逻辑过多应该抽取到 Model 或者 lib

http://ruby-china.org/topics/10438#reply3

#11 楼 @Rei 有的插入执行很快,有的插入执行很慢。这个我再研究吧。 你的提议我继续优化,非常感谢~

#12 楼 @Rei lib 是不是相当于 java 里面的 service 层了呢?我印象中的 lib 就是类库了。。

#14 楼 @jarorwar lib 就是个文件夹,不属于 model 的逻辑就放这里。

#15 楼 @Rei 恩。那么想这个 excel 的内容读取就可以放这里了。但是每一行解析后都对应的是 model 的你个实例啊。在 lib 里面再引入 model 的类,对吧

#16 楼 @jarorwar lib 里面的代码可以调用 model。

#17 楼 @Rei 好的。灰仓感谢啊

#16 楼 @jarorwar 要放在 lib 里面还要在 config/application.rb 里面加上这个配置:

config.autoload_paths += %W(#{config.root}/lib)

并且 lib 里面的模块和类要遵循文件名约定

# lib/foo.rb class Foo end

觉得麻烦就先放在 Model 里。

#19 楼 @Rei 恩。因为刚开始接触这个的东西,所以有时候看着不妥的东西,却不知道怎么弄。你这就给我指名道路了。我还是尝试放 lib 吧。model 太大其实我也很不适应。因为 java 里面的 model 就是那么的单纯~

我可以这么理解吧。其实在做 rails 的时候。一个 model 对应一个 controller 到 view,跟 model 相关的简单逻辑,例如:crud,这些可以放在 model 里面做。比如有更负责的逻辑。例如下订单。处理一些别的数据(跟 model 对应不起来的)就可以放在 lib 里了。另外,controller 对应的 rest url 有 edit,view,delete ,create。如果要加跟这些无关的。例如上传一个 excel。我这个 action 放在对应的 aiction 里面是否可以?

#7 楼 @jarorwar 对于你的这个需求,假如所有人的所有考勤记录的字段信息都相同,不能放到一个 FingerPrint 数据库表里面吗?然后一个 Finger_print model 就可以管理了。

#21 楼 @jarorwar 不推荐都往 lib 里面放,lib 相当于 “其他”,如果有明确的分类,可以在 app 下新建文件夹,比如 app/uploader,app/whatever。

少量的业务逻辑写在 Model 里面没问题,觉得不好管理了再分出去。

model controller 不必要一一对应。resources 路由没有的 action 可以自己加,具体看官方文档。

#22 楼 @saillee model 现在是一个。这个是基础信息。 还有另外一个是最终的结果 。例如 Finger_print model 的记录为

姓名 上班时间 下班时间 a 2013-04-09 12:38:21 2013-04-09 19:38:21

对应的结果应该是 2013-04-09 姓名 上班 | 下班 a 迟到 | 正常

#23 楼 @Rei ok,谢谢~

#24 楼 @jarorwar 这样就很简单了,再做一个上班时间的定义表,上班时间在此定义中范围内就视同迟到,下班时间在此定义范围的就视同早退,这样定义还能针对不同的工种进行不同时间的定义,估计一个 SQL 就能全部判别完了。其实我感觉这个是系统设计的问题。

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册