Together网站搭建之踩坑系列4

写在前面

这是功能实现的第三篇,扯一扯如何添加省市自治区地址, 并实现热门城市筛选功能

完整作品源码及效果,看这里作品网站, 作品源码

目录

正文

先说如何添加省市区地址

上效果图:

Step1、安装相应的gem及配件

  • 在gemfile中添加:

    gem 'china_city'
    
  • 终端运行:bundle install

  • app/assets/javascripts/application.js中,添加:

    //= require jquery
    //= require 'china_city/jquery.china_city'
    

    注意:如果文件中已经添加了jquery, 则无需再添加

  • config/routes.rb中添加:

    mount ChinaCity::Engine => '/china_city'
    

Step2、使用

代码以together网站为例

  • 给event添加省区、城市栏位,终端运行:

    rails g migration add_province_and_city_to_events
    

    修改db/migration/xxx_add_province_and_city_to_events:

    class AddProvinceAndCityToEvents < ActiveRecord::Migration[5.0]
      def change
        add_column :events, :province, :string
        add_column :events, :city, :string
      end
    end
    

    终端运行:rake db:migrate

  • 将新增的province,city添加到app/controllers/events_controller.rb的params中。

      def event_params
      -  params.require(:event).permit(:title, :logo,.....)
      +  params.require(:event).permit(:province, :city, :title, :logo,.....)
      end
    
  • 在events的new.html.erbedit.html.erb中添加如下代码, 让用户新建活动时选择省市区:【这里是用simple_form格式】

     ......
     <div class="form-group">
        <div class="city-group">
          <%= f.select :province, ChinaCity.list.unshift(["--省份--", 230000]), {}, class: "city-select"%>
          <%= f.select :city, ChinaCity.list(f.object.province).presence || [["--城市--", 230900]], {}, class: "city-select"%>
        </div>
      </div>
      ......
    
  • 回显省份及城市,这里,在需要回显的地方, 如index页面,添加如下代码:

    <% @events.each do |event| %>
    ......
        <div class="city">
          <%= ChinaCity.get(event.province) %> - <%= ChinaCity.get(event.city)%>
        </div>
    .....
    

    这里,显示的都是XX省XX市, 如果只希望显示城市, 且没有”市”这个后缀,可以改成:

    <% @events.each do |event| %>
    ......
        <div class="city">
          <%= ChinaCity.get(event.city).split("市").first %>
        </div>
    .....
    

OK!

接下来,看看如何实现热门城市筛选功能。

上效果图:

Step1、建model

  • 建立city model,终端运行:

    rails g model city city:string
    rake db:migrate
    
  • 这里,为了跟ChinaCity中城市的行政区划代码保持一致,在app/models/city.rb中,添加了北上广深杭州,成都的行政区划代码:

    class City < ApplicationRecord
    
     + CITY = ["110000","310000","440100","440300","330100","510100"]
     + validates_inclusion_of :city, :in => CITY
    
    end
    

    BTW,最开始的时候,我想着如果根据活动添加的情况,将所有出现的city都罗列出来,那这个筛选项就是动态的,可能存在并发的情况,固定城市反而更好。

  • 在seeds文档中,添加如下代码:

    # City部分
    City.delete_all
    
    City.create!(city: "110000")
    City.create!(city: "310000")
    City.create!(city: "440100")
    City.create!(city: "440300")
    City.create!(city: "330100")
    City.create!(city: "510100")
    

Step2、添加城市列表筛选

  • 显示筛选项,在events的 index.html.erb中,添加如下代码:

    <div class="submenu" style="margin-bottom: 3px;">
      <span><i class="fa fa-paper-plane fa-lg"></i> 城市: </span>
      <div class="btn-group" style="margin-left: 20px;">
        <%= link_to "全部", events_path, :class => "btn btn-default btn-group #{(params[:city].blank?)? "active" : ""}"%>
        <% City.all.each do |c| %>
          <%= link_to ChinaCity.get(c.city).split("市").first, events_path(city: c.city), :class => "btn btn-default btn-group #{(params[:city] == c.city)? "active" : "" }"%>
        <% end %>
      </div>
    </div>
    
  • event.rb中加入以下代码:

    scope :by_city, ->(c){where( :city => c )}
    
  • events_controller.rb,添加如下代码:

      def index
        @events = Event.order("created_at DESC")
        ......
      + if params[:city].present?
      +  @events = @events.by_city(params[:city]).order("created_at DESC")
      + end
      end
    

做到这里,试一试筛选功能,你会发现一个bug,直辖市是筛选不出来的,比如北京,上海这种,怎么回事?

因为这些市,保存在了province这个栏位里面,而它们对应的city则保存了“市辖区”,“县”对应的区划代码。我们来修改一下:

  • events_controller.rb,对于create部分,做如下修改:

      def create
        @event = Event.new(event_params)
        @event.user = current_user
      +  if ChinaCity.get(@event.city) ==  "市辖区" || ChinaCity.get(event.city) == "县"
      +   @event.city = @event.province
      + end
        ......
      end
    

    现在试试,可以筛选啦!

P.S. 是不是发现跟前面一篇添加分类筛选有相似之处?

参考:

省市区详细地址教程

Rails Engine Gem China_City