Rails 如何在 view 中 render controller 的参数

roccia · 2016年05月06日 · 最后由 leoyuan1986 回复于 2017年10月08日 · 3827 次阅读

想要把用户选择的日期范围(start_date, end_time)作为参数,从 view 传回到 controller, controller 里调用传进的参数计算并返回结果,再将结果传回 view, 我用的是 bootstrap-datepicker gem, 用 ajax 来实现 view ---controller 的参数传递,我的确把选择的日期传到了 controller, 并得到了结果,可是在 view 里面 当我想要重新 render 这个结果的时候浏览器返回却是空。

详细代码如下 Controller analyzer_controller.rb

def data

start_time = params[:start_date]?   #[:start_date] ---> ajax的参数
        Date.parse(params[:start_date]) :Date.iso8601   
end_time =  params[:end_date]?
        Date.parse(params[:end_date]) :Date.iso8601

# 需要把@iphone 和@android的结果传到view
     @iphone =Analyzer.new.   
      mobile_type_count('deviceOS','mobileNum','$deviceOS',
                        '$mobileNum','iOS' , start_time , end_time  )
      @android = Analyzer.new.
      mobile_type_count('deviceOS','mobileNum','$deviceOS',
                        '$mobileNum','Android' ,  start_time, end_time )

 end

Model analyzer.rb


def mobile_type_count(name,name1,field, filed1,value, start_time, end_time )

date_match = {:$match  => {:created_at => { :$gt =>  start_time , :$lt => end_time  }}}   #选择的日期传入到这里,根据日期用mongo聚合来计算
 ......... 
  end

** View data.html.erb **

<div class="input-daterange input-group" id="datepicker">
    <input type="text" class="input-sm form-control" name="start" value="2016-04-11" id="startDate" />
    <span class="input-group-addon">to</span>
    <input type="text" class="input-sm form-control" name="end" value="2016-04-13" id="endDate" />
  </div>
    <%=   button_tag(type: 'submit', class: "btn btn-default btn-sm", :id => 'get_data' ) do %>
        Submit

    <% end %>
</div>
<div class="ibox-content">
      <%=  pie_chart({"iphone" => @iphone, "android" => @android}) %>         
    </div>

当点击 submit 的时候,页面没有返回任何值,或者图表,浏览器返回的是:

<script type="text/javascript">
  new Chartkick.PieChart("chart-1", {"iphone":[],"android":[]}, {});
</script>

也就是说@iphone@android 要不就是没有传过来,要不就是传过来了但是没有正确的被 render, 我用 puts 来测试的时候

<%=  puts  pie_chart({"iphone" => @iphone, "android" => @android}) %>

在 Terminal 里面可以看到以下输出:

<script type="text/javascript">
  new Chartkick.PieChart("chart-1", {"iphone":[11],"android":[10]}, {});

Ajax

<script type="text/javascript">


  $(document).ready(function() {

  $('#get_data').click(function(){
        var sd = $('#startDate').val(),
            ed = $('#endDate').val()
    $.ajax({
      url: "/analyzer/data",
      type: "post",
      data: {'start_date' :sd, 'end_date': ed},      

      success: function(){
      },
      error:function(){
        alert('Error');
      }
    });
  });

为什么在 Terminal 里可以得到 iphone 和 android 的结果呢?希望有人能给我解释解释 谢谢!

代码截图吧,乱东西没人看的吧。

#1 楼 @chenge 这样算乱吗。。我再编辑一下。。。

#2 楼 @roccia 电脑上看正常,手机上看不行。 你似乎用了 js 插件 piechart。看是否把问题细分一下,目前不容易看懂。

#3 楼 @chenge piechart 是 chartkick gem 的一个方法,piechart 的参数可以是数组也可以是 hash。具体是哪里没写好呢,我已经很详细的把每一部分代码都贴出来了啊,我再把问题描述写清楚一些

你的预期是图么,返回是 js 代码吧。

#5 楼 @chenge 预期是返回图表,我上面贴出来的是浏览器返回的 js 代码,因为必须@iphone@android不为空才能返回图表啊,我测试过不是 piechart 的问题,如果我直接在 model 里设置好具体时间,view 是可以显示正确图表的

是 ajax 的问题吧。控制器加 puts 看运行情况。

#7 楼 @chenge 试过了 puts @iphone 和 puts @android, 或者 puts start_time, puts end_time, 都可以在 terminal 里得到结果

ajax 应该有返回处理吧,估计是 ajax 协议问题。

#10 楼 @roccia 建议先用静态页面方式。再研究下 ajax 原理。回到基础,不能靠猜。

  • 按原意:返回 render 的 view, view 里 js 未执行。js 获取到返回值,及一段 html,js 并不会解析这段 html,需要加在 html,如$(container).html(html)

  • 其实,不需要重复返回 view。只将你的统计数据返回为 json,{"iphone":[11],"android":[10]},并在 ajax success 时执行图表绘制就 OK 了。

# controller
def data
 if request.post?
   ......
   .....
   render json: {iPhone: @iphone, android: @android}
 end
end

// js
$.ajax({
      url: "/analyzer/data",
      type: "post",
      data: {'start_date' :sd, 'end_date': ed}, 
     dataType:'json',
      success: function(data){
         // add to here
          new Chartkick.PieChart("chart-1", data, {});
      },
      error:function(){
        alert('Error');
      }
    });
  • 还有方式,比如你 ajax dataType 为 script,然后后端 返回一段 js。这个就不细说了:)

#11 楼 @chenge 静态页面完全没问题 显示都正常,我把能想到的测试方法都用上了,真的很头大啊,看了很多资料,没发现有人用相同或者相似的方法来对 mongo 进行根据日期查询,这个 bug 卡了一周了。。。

#12 楼 @mueven 啊啊啊 it works!!! 太感谢了

@roccia , 你是怎么做 mongo 查询时间的?什么 bug?详细的看看。

#15 楼 @mueven 我用的 mongoid,然后用 mongo aggregation , 查询这里没有 bug ,我说的 bug 就是上面的问题,这个是根据时间查询的方法


class Analyzer
  include Mongoid::Document
  store_in collection: 'tx_test'

 def mobile_type_count(name,name1,field, filed1,value, start_time, end_time )

    date_match = {:$match  => {:created_at => { :$gt =>  start_time , :$lt => end_time  }}}
    match = { :$match => {name => value}}
    group ={:$group =>{ :_id =>
                             {name => field,
                              name1 => filed1},
                         :count => {:$sum =>1}
    }}
    group1 = {:$group =>{:_id =>
                              { name => field,
                                name1 => filed1},
                          #:totalCount=> { :$sum => '$count' },
                          :distinctcount => {:$sum => 1}
    }}

    mobile_usr= collection.aggregate([date_match,match,group,group1])

    mobile_usr.map do |m|
      m[:distinctcount]
    end
  end

#15 楼 @mueven 搜了一圈 没有找到相似的案例

@roccia :( 这种分组的查询没有使用过

#15 楼 @mueven 还有 2 个困惑,

  1. 现在图表显示正确了 可是我有多个图表需要展示,比如
<div class="col-lg-4">
 。。。。。。。。。。
            <%=   button_tag(type: 'submit', class: "btn btn-default btn-sm", :id => 'get_data' ) do %>
                Submit
            <% end %>
          </div>
          <%= pie_chart({"未注册" => @unreg_user, "注册" => @reg_user}) %>

        </div>
      </div>
    </div>

我想到的一个笨办法是 把所有要展示的图表都单独写到_chart1.html.erb, _chart2.html.erb 等等 里面,可是这样就不符合 DRY 原则了 可我注意到 在 js 里面

success: function(data){
            new Chartkick.PieChart("chart-1", data, {});
           },

只是 return 了一个表,如何让他根据不同的 div 显示不同的图表呢?我需要在 controller 里面再写一个 render json: {未注册:@unreg_user, 注册:@reg_user} 吗

  1. 在 view 里面:
    ruby <%= pie_chart({"iphone" => @iphone, "android" => @android}) %> 这一行为什么不能删掉呢?我刚试了下 删除后 就没有图了

#18 楼 @mueven 就是 mongo 聚合,功能还是挺强大的,不太明白你说的分组的意思。

#19 楼 @roccia

  • 为什么删掉不能用,具体的这个库我没用过,据我推测:会生成一个容器“chart-1”吧,这样才可以在 js 里使用

  • 多个图:每个图其实基本上都是 Pie 图?只是统计的值类型不一样。那么你给后台一个这个类型,后台判断统计,然后给 js。这里 js 生成图表应该和统计类型无关的,就是找到一个容器,放入 kv 值。(如果想要更多,你可以多尝试。个人觉得你设计好不同函数的输入和输出,就可以减少冗余了)

#21 楼 @mueven 谢谢 我再仔细研究研究

楼主在不在?我现在也遇到了你那个 ruby 中使用 mongo 聚合函数 match 时间的问题,不知道你那边解决了没有?

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