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

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

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

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

very thx!!!

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

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

跟写在 controller 区别不大吧

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

@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 里面 但是返回消息成了问题 感觉总不方便

巨汗.....

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

我提出幾個建議。

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

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

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

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

可以试一下用 draper

#1 楼 @xdite 感谢你的文章

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

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

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

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

@hbin 挖坟啊。。。。。。

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