-
Notifications
You must be signed in to change notification settings - Fork 107
DIY menu
lanrion edited this page Apr 19, 2014
·
5 revisions
- gem 'rails', '4.0.2'
- gem 'jbuilder', '~> 1.2'
class CreateDiymenus < ActiveRecord::Migration
def change
create_table :diymenus do |t|
t.integer :public_account_id
t.integer :parent_id # 所属父级菜单,如果当前是父级菜单,则此值为空
t.string :name
t.string :key
t.string :url
t.boolean :is_show # 是否显示
t.integer :sort # 排序功能
t.timestamps
end
add_index :diymenus, :public_account_id
add_index :diymenus, :parent_id
add_index :diymenus, :key
end
end
class Diymenu < ActiveRecord::Base
CLICK_TYPE = "click" # key
VIEW_TYPE = "view" # url
belongs_to :public_account
has_many :sub_menus, ->{where(is_show: true).order("sort").limit(5)}, class_name: "Diymenu", foreign_key: :parent_id
def has_sub_menu?
sub_menus.present?
end
# 优先为 click 类型
def type
key.present? ? CLICK_TYPE : VIEW_TYPE
end
def button_type(jbuilder)
is_view_type? ? (jbuilder.url url) : (jbuilder.key key)
end
def is_view_type?
type == VIEW_TYPE
end
end
class PublicAccount < ActiveRecord::Base
# 自定义菜单
has_many :diymenus, dependent: :destroy
# 当前公众账号的所有父级菜单
has_many :parent_menus, ->{includes(:sub_menus).where(parent_id: nil, is_show: true).order("sort").limit(3)}, class_name: "Diymenu", foreign_key: :public_account_id
def build_menu
Jbuilder.encode do |json|
json.button (parent_menus) do |menu|
json.name menu.name
if menu.has_sub_menu?
json.sub_button(menu.sub_menus) do |sub_menu|
json.type sub_menu.type
json.name sub_menu.name
sub_menu.button_type(json)
end
else
json.type menu.type
menu.button_type(json)
end
end
end
end
end
# 结合: https://github.com/lanrion/weixin_authorize(建议选用此gem的Redis存access_token方案)
def generate_menu
weixin_client = WeixinAuthorize::Client.new(@current_public_account.app_key, @current_public_account.app_secret)
menu = @current_public_account.build_menu
result = weixin_client.create_menu(menu)
set_error_message(result["errmsg"]) if result["errcode"] != 0
redirect_to public_account_diymenus_path(@current_public_account)
end
Action 层:
if $weixin_authorize.is_valid?
build_result = $weixin_authorize.create_menu(Diymenu.build_menu)
msg = "build menu successfully." if build_result.ok?
else
msg = "invalid appid or appsecret."
end
redirect_to admin_diymenus_path, notice: msg
Model层
class Diymenu < ActiveRecord::Base
validates_uniqueness_of :name
CLICK_TYPE = "click".freeze # key
VIEW_TYPE = "view".freeze # url
has_many :sub_menus, ->{where(is_show: true).order("sort").limit(5)}, class_name: "Diymenu", foreign_key: :parent_id
belongs_to :parent, foreign_key: :parent_id, class_name: "Diymenu"
def has_sub_menu?
sub_menus.present?
end
# 优先为 click 类型
def type
key.present? ? CLICK_TYPE : VIEW_TYPE
end
def button_type(jbuilder)
is_view_type? ? (jbuilder.url url) : (jbuilder.key key)
end
def is_view_type?
type == VIEW_TYPE
end
class << self
def parent_selection(current_menu)
where.not(id: current_menu.id).map{|menu| [menu.name, menu.id]}
end
def parent_menus
includes(:sub_menus).where(parent_id: nil, is_show: true).order("sort").limit(3)
end
def build_menu
Jbuilder.encode do |json|
json.button (parent_menus) do |menu|
json.name menu.name
if menu.has_sub_menu?
json.sub_button(menu.sub_menus) do |sub_menu|
json.type sub_menu.type
json.name sub_menu.name
sub_menu.button_type(json)
end
else
json.type menu.type
menu.button_type(json)
end
end
end
end
end
end