Rails 困惑!helper里面写查询好不好

tumayun · 发布于 2012年03月19日 · 最后由 tumayun 回复于 2013年04月18日 · 2862 次阅读
967

来到新公司,发现很不适应,以前写代码都是严格遵守自己理解的mvc模式来写的代码, 在model里面写逻辑,写查询,在controller中调用,view里面最多加点判断, but: 在新公司,view里面到处都是helper方法,helper里面到处都是find以及一些逻辑, action里面都是不写东西的,问了同事,因为要加缓存,所以不在action写,而在view里面写,这样能理解,但是看写来感觉有点怪!!! 有没有更好的解决方案,或者这样就是正常的???

本人是一年rails的新人,希望各位前辈解惑 and 科普下...

very thx!!!

共收到 36 条回复
196

不好 http://erp-book.heroku.com/ch4-helper-antipatterns 我寫的 Helper Antipatterns

713

把所有的model方法都写在controller里那才叫一个恐怖

16

这么说来。。楼主的项目是rails2的咯?

200

用scope

947

跟写在controller区别不大吧

686

@xdite 看了你发的helper的post,然后留了一个问题,请解答一下

196

哦。我的標題的確寫錯了。感謝你的指正

686

@xdite 那我偷帖子咯 不介意吧 大大

1

Rails 3的话,主体部分查询不写在 action 就不对了。现在查询都是延迟执行的,跟片段缓存不冲突。(Rails 2 没办法)

非主体部分的查询写 helper 我能接受,应用比较广的查询移到 model。

686

那请问 把各种方法 放在 models中 状态 通知是怎么做的呢 是不是 model返回一个 状态值 然后在controller中 匹配一个字典来给用户返回 flash:notice 么 还是尽量 独立每个method 然后在controller中 做状态控制呢 ,我做的支付 就是想了 半天 结果还是把方法放在 controller 知道不好 我也那样做了 嘿嘿

96

#4楼 @ywencn 应该是rails-2 了。rails-2没有延迟加载,放在controller里的话,每次请求都会去查询。

一般情况下,把查询写在views或者helper里,会比较慢。当然这是第一次请求比较慢,如果做了片段缓存,下次请求就很快了。

在某些变态需求里,页面内容很多,有很多 @Rei 所说的非主体部分,放在controller里查询可能会很多,导致controller很大很乱,偏离了controller的目的。我觉得,对于那种可能出现当前请求返回404的查询,必须放在controller里,其他的可以放在其他地方。

当然,放在view或者helper里,管理起来也不轻松。我们写程序可以一个方法只做一件事情,但是很多人设计的页面里,一个页面,非得做N件事情,就不能用程序员的逻辑去想了⋯⋯呵呵

总之:放在helper里,是为了片段缓存。

96

还有一些查询,会放在partial里,然后缓存一下。 比如那些很多地方都使用的partial。 @xdite 曾经有一篇blog Rails Performance Tuning (2) – 在 partial 裡面下 query 再做 cache

1

#11楼 @jhjguxin 这……不是只读查询的场合么,flash是要放什么?

#12楼 @zhangyuan 确实,我就不明白为啥一个页面非要做N件事,哈哈。相关文章,月排行,最新评论什么的我觉得根本不会有人去看。

16

rails2可以在控制器里加判断 if Rails.cache.has_key? xxx

686

@Rei 我只是搭顺风车 问问 我遇到的问题吗 各位 有什么好的 建议么

1

#16楼 @jhjguxin 可以尝试和 ActiveRecord#errors 的处理一样

686

@Rei 也就是说自己做一个 返回状态的轮子 么 还是直接用 errors字典

586

我觉得如果需要在Helper里面写model查询的话,你可以去看看cell这个东西

686

@xdite 请问 把各种方法 放在 models中 状态 通知是怎么做的呢 是不是 model返回一个 状态值 然后在controller中 匹配一个状态hash字典来给用户返回 flash:notice 么 还是尽量 独立每个method 然后在controller中 做状态控制呢 ,我做的支付 就是想了 半天 结果还是把方法放在 controller 知道不好 但是没有什么 直观简洁的方法来 返回 业务状态 也不知道是不是我的models method 不够独立苗条

196

可以給我 code sample 嗎?你這樣敘述我聽不是很明白

686

@xdite

def checkoutorder(tradeinfo=nil,user=nil)
    unless tradeinfo.nil? and user.nil?
        #breakpoint
      if user.wallet
        if user.wallet.balances>=tradeinfo.total
        #breakpoint
         return flash[:notice] = "You have aleady pay for this order!" if tradeinfo.paystatus==true
          flash[:notice] = "Pay for this order,by #{user.username} successfully!" if tradeinfo.update_attributes(:paystatus=>true)
          note="payment by #{user.username}"
          user.wallet.update_attributes(:balances=>user.wallet.balances-tradeinfo.total)
          Moneyrecode.new(:wallet_id=>user.wallet.id,:payment_type=>-1,:sum=>tradeinfo.total,:note=>note).save
        else
          flash[:notice] = "Your balance is less than the sum of this order!" 
        end
      else
        flash[:notice] = "Your wellet has not created! Please nagivate to walltes" 
      end
    end
  end

  #class << self
  def checkandsave(tradeinfo=nil,product=nil,user=nil,order_count=1)
    unless tradeinfo.nil? and product.nil? and user.nil?
      if product.count-order_count>=0
        pay_price=(product.price*product.discount)

        total=pay_price*order_count
        per_trade_sum=PaymentChina::Config.default[:per_trade_sum]
        if per_trade_sum>=(tradeinfo.total+total)
          product.update_attributes(:count=>(product.count-order_count))
          if old_trade=tradeinfo.trades.find_by_product_id(product.id) and not(tradeinfo.paystatus)
            if old_trade.product_price==product.price and old_trade.product_discount==product.discount 
              #breakpoint
              #old_trade.update_attributes(:total=>(old_trade.total+=total),:product_count=>(old_trade.product_count+=order_count))
              old_trade.update_attributes(:product_count=>(old_trade.product_count+=order_count))
              flash[:notice] = "Add #{product.name} to shopping basket successfully" 
            end
          else
            newtradeinfo=tradeinfo.trades.new(:product_id=>product.id,:tradeinfo_id=>tradeinfo.id,:product_count=>order_count,:product_name=>product.name,:product_price=>product.price,:product_discount=>product.discount,:pay_price=>pay_price,:total=>total,:product_category_id=>product.category_id)
            flash[:notice] = "Creat a new shopping basket,and add #{product.name} successfully"

          end
          #breakpoint
        end      
      end
    #product.update_attributes(:count=>(product.count-order_count))
    end
  end

https://github.com/jhjguxin/payment-china 我尝试过吧method放在 model里面 但是返回消息成了问题 感觉总不方便

196

巨汗.....

686

@xdite 我知道我的代码 不规范 也不美观 我在努力

196

我提出幾個建議。

  1. 其實你可以改成用 model validator 去做, 把錯誤加在 product.erros 裡面 http://juixe.com/techknow/index.php/2006/07/29/rails-model-validators/

  2. 你的代碼太高耦合了。不 refactor 掉以後沒人能維護...

686

@xdite 嗯 毕竟 我这个只是一个demo 也没人告诉我该怎么做 也就是 针对每个method 定制 多种 错误状态,通过 errors字典来返回么 http://guides.rubyonrails.org/active_record_validations_callbacks.html 明天我好好重写一下 呵呵 谁维护我的代码 还不如重写一个呢

967

今天太忙了,刚刚回到家,正在看贴。。。谢谢各位!!

304

可以试一下用draper

967

#1楼 @xdite 感谢你的文章

686

@xdite 谢啦 嘿嘿 我一定 把 method 找个好位置放进去 太高端了

967

确实是rails2的项目,以后要换到rails3.2.2上,现在项目是的真的很乱,至少我感觉是这样, 有写的很好的代码,但是有的代码真的很烂,连我这个菜鸟都看不下去。。。

1756

#3楼 @azhao 更恐怖的是, model的方法都放在controller里,可是偶们技术主管的要求的"正确"做法哦.

2746

#33楼 @tumayun 还是没换....

967

@hbin 挖坟啊。。。。。。

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