1.配置用户超时
<Project>/config/initializers/devise.rb
编辑 # config.timeout_in = 30.minutes 这一行,修改为想要配置的时间
<Project>/app/models/user.rb
配置devise :database_authenticatable, :registerable,这一行,加上 :timeoutable
2.设置用户单处登陆
原理:devise在用户登陆后会设置users表中的current_sign_in_at字段为最后一次登陆的时间,用户每次登陆后在session中保存current_sign_in_at字段,在application中校验session中current_sign_in_at字段,如果为空或者小于current_user对象的current_sign_in_at则强制注销
1) 在application_controller基类中定义after_sign_in_path_for方法在当中设置session对象
def after_sign_in_path_for(resource) session[:current_sign_in_at] = current_user.current_sign_in_at root_path end
2) 定义has_signed取代:authenticate_user!判断用户登陆
def has_signed unless user_signed_in? redirect_to root_path else if session[:current_sign_in_at] == nil or session[:current_sign_in_at] < current_user.current_sign_in_at redirect_to destroy_user_session_path end end end
3)在需要判断用户登陆的controller中添加before_action :has_signed过滤器。
给rails系统加i18n,根据浏览器的头去识别用户语言。记录一下相关实现:
1. 添加i18n配置
# config/application.rb
config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**', '*.{rb,yml}')]
config.i18n.available_locales = [:en, :cn]
config.i18n.default_locale = :cn
2. 获取语言设置
# app/controller/application_controller.rb before_action :set_locale # set local {{{ def set_locale I18n.locale = get_locale end # }}} # locale {{{ def get_locale locale = I18n.default_locale if params[:locale] locale = params[:locale].downcase elsif cookies[:locale] locale = cookies[:locale] elsif locale = get_accept_language locale end # set cookies if cookies[:locale] != locale cookies[:locale] = locale end locale end def get_accept_language begin first_lang = request.env['HTTP_ACCEPT_LANGUAGE'].split(';').first default_lang = first_lang[0,2].downcase if default_lang == 'zh' first_lang[3,2].downcase else default_lang end rescue nil end end # }}}
说明:locale的值优先从url地址读取,次之从cookie,最后从浏览器头判断。英文浏览器的头为Accept-Language:en-US,en;,取en即前两位。中文浏览器头为Accept-Language:zh-CN,zh;,取cn即3-5位,转为小写。
3.编辑语言文件
# config/locales/en.yml
en:
hello: "Hello world"
# config/locales/cn.yml
cn:
hello: "你好"
4. 在模板文件中应用
# app/views/home/index.html.erb
<p><%= t('hello'); %></p>
<ul>
<% I18n.available_locales.each.each do |locale| %>
<li><%= link_to locale, params.merge(locale: locale) %></li>
<% end %>
</ul>
说明:点击生成的链接可以手动切换语言,测试的时候方便一些。
devise默认已经有较好的ajax支持了,只需要简单的配置一下即可使用ajax登录/注册。
1. 修改config/application.rb加下以下配置,启用json输出。
# devise respond_to json config.to_prepare do DeviseController.respond_to :html, :json end
2. 修改form标签,添加data-remote, data-type,设置id
<%= form_for(resource, :as => resource_name, :url => session_path(resource_name), :remote => true, html: {id: 'ajax_user_signin', data: {type: :json}}) do |f| %>
3. 设置ajax头
$.ajaxSetup({ beforeSend: function(xhr){ var token; token = $('meta[name="csrf-token"]').attr('content'); if (token) { xhr.setRequestHeader('X-CSRF-Token', token); } } });
4. js处理代码
$('#ajax_user_signin').on('ajax:complete', function(e, xhr, type){ if (type === 'success') { location.href = '/'; } else { try { alert(xhr.responseJSON.error); // this.reset(); } catch (e$) { e = e$; } } });
关于注册:
注册的方法和登录基本相同,给form_for添加data-remote、data-type和id等属性。需要注意的是注册返回的表单验证是多项错误,使用xhr.resonseJSON.errors获取错误集合。
使用devise这个gem只需要简单几步就能做好用户注册登录等功能,能节省大量时间和精力。
1. 安装devise
# 编辑Gemfile加入以下内容
gem 'devise'
#安装gem
bundle install
#初始化devise
rails g devise:install
#初始化model为user
rails g devise user
#初始化视图
rails g devise:views
# 创建数据库
rake db:migrate
2. 使用
# 创建一个空的controller
rails g controller home index --no-helper --no-assets
# 编辑config/routes.rb将home index设为首页
root 'home#index'
# 编辑app/views/home/index.html.erb加入以下内容
<h1>Home#index</h1> <% if user_signed_in? %> hello, <%= current_user.username %><br /> <%= link_to('登出', destroy_user_session_path, :method => :delete) %> <% else %> <%= link_to('注册', new_registration_path(:user)) %> <%= link_to('登录', new_session_path(:user)) %> <% end %>
此时访问http://localhost:3000就可以使用注册登录功能了。
另附两个有用到的链接:
1. 添加用户名登录 How To: Allow users to sign in using their username or email address
2. 添加管理员角色 How To: Add an Admin Role
自从装了QQ,总习惯点开QQ空间,久之成瘾。最近改版之后弄得很郁闷,每次打开照片预览,“猜你喜欢”都正好挡住照片评论。
经常到豆瓣听民谣和DJ录音,用了大半年,有几点比较不爽,吐槽之
1. 奇葩的音乐人搜索
在music.douban.com上面的搜索,输入“宋冬野”,自动完成的提示里面有音乐人的小站,搜索的结果却另一翻模样。这个自动完成的功能是新加的,之前在这个位置搜不出音乐人。
如果你想搜索音乐人,得点到音乐人页面,拖到第二屏,用藏着的一个搜索框
2. 同一个页面多个专辑的播放不能互斥。
同一个页面,点开了一张专辑的歌曲,再播放另一张专辑的歌曲时。先前的播放不能自动停止。
3. 总是飘着的分享框
鼠标移动到播放列表中的rss图标,会出现一个悬浮的分享框。鼠标移到悬浮框,往右移出去,悬浮框会一直存在。在停止一首歌然后中键滚动的时候,肯定多出这个家伙在你眼前。打酱油的前端呀!
4. 分享的播放链接
分享的播放链接大约是一个这样的地址,http://site.douban.com/qikeqike8/room/1968340/?s=396923 会播放id为396923的歌曲。当一个页面列有大量歌曲的情况下,不知道当前播放的是哪一首。知道有个东西叫锚点么?不知道把页面滑动到正在播放的歌曲位置么?
最近装了“*城宽带”,发现打开网站时还会弹出广告。打电话给客服沟通,客服表示不知道他们有广告,声称是我本人电脑设置有问题。很无耐,写一代理用来屏蔽广告。
下载地址:http://pan.baidu.com/share/link?shareid=3835585554&uk=590772501#dir/path=%2Fpub%2Fother下载adbreak.zip
使用方法:
1. 解压软件包,点击adbreak.bat
软件启动后如下图:
2. 设置浏览器代理脚本配置,以IE为例。(firefox使用autoproxy、chrome使用proxy-switchysharp将指定网址的代理定向到 8337端口,使用goagent也可以直接修改GoAgent Pac文件,参照adbreak.pac)
工具->Internet选项->链接->局域网设置 勾选 “使用自动脚本配置” 在下面的“地址”这一栏填入 http://127.0.0.1:8337/break.pac
3. 设置屏蔽的网址:
编辑break.pac脚本,在 disable_url 中添加要屏蔽的网址。默认带的几个网址是用来屏蔽“*城宽带”这边的几个广告的。
4. 如何知道广告的网址?
首先建议使用抓包工具,如果没有抓包工具可以使用adbreak自带的代理来查看地址。
设置方法:将第2条中的设置地址改为http://127.0.0.1:8337/proxy.pac。
这时再用浏览器上网,所有的请求是走的adbreak自带的http代理访问,会将网址打印在地址栏中。使用浏览器浏览网页,弹出广告后,查看adbreak中的地址列表,找出广告地址。(你访问网址被拦截后的第一条)
由于cmd自带的缓冲区显示内容有限,需要将修改缓冲区大小,以显示足够多的请求地址。
设置方法:鼠右键点击adbreak标题栏,选择属性->布局 “将屏幕缓冲区大小”中的“高度”设为 5000
说明:程序使用nodejs运行,启用后占用 8337、8338 两个端口,8337端口有break.pac和proxy.pac两个文件。
使用break.pac文件时,当弹出ISP的广告时,break.pac脚本识别到广告地址将这个请求定向到8337端口,这时原请求地址被附加在广告请求地址的Referer中,代理读取referer地址,将请求重定向到原地址。
使用proxy.pac时,请求请重定向到8338端口,这时所请求的文件通过adbreak从网络获取,可以得到每一个请求的地址。用来从地址列表中找出广告的地址。
附adbreak的coffee源代码:
http = require 'http' url = require 'url' http.createServer (req, res)-> request_url = req.url request_pac = request_url.match /\/((?:break|proxy).pac)((?:\?.*)?)/ if request_pac isnt null console.log "[#{req.method}] #{request_url}" res.writeHead 200, 'Content-Type': 'application/x-ns-proxy-autoconfig' pac = require('fs').createReadStream request_pac[1] pac.pipe res pac.on 'end', -> res.end() else referer = req.headers.referer if referer console.log "[#{req.method}] -referer- #{request_url}" res.writeHead 302, 'Location': referer else res.writeHead 200, 'Content-Type': 'text/plain' console.log "[#{req.method}] -disable- #{request_url}" res.write 'no referer' res.end() return .listen 8337, '0.0.0.0' console.log 'start break server by http://127.0.0.1:8337' http.createServer (req, res)-> # 请求地址 request_url = req.url # 请求记录 console.log "[#{req.method}] #{request_url}" # 请求数据 post_data = '' request_option = url.parse request_url request_option.method = req.method request_option.headers = req.headers # 接收数据 req.on 'data', (chunk)-> post_data += chunk return # 结束请求 .on 'end', -> if request_option.method is 'POST' then proxy_request.end post_data else proxy_request.end() return # 开始代理请求 proxy_request = http.request request_option, (result)-> # header headers = result.headers # statusCode statusCode = result.statusCode # 写入头 res.writeHead statusCode, headers # 写入代理数据 result.on 'data', (chunk)-> res.write chunk return # 数据结束 result.on 'end', -> res.end() return return # 错误处理 .on 'error', (error)-> res.end "remote http.request error#{error}" return return .listen 8338, '0.0.0.0' console.log 'start proxy server by http://127.0.0.1:8338'
附使用截图:
“*城宽带”拦截网络访问弹自家广告抓包截图:
可以看到访问www.jd.com被强制转向到了count.chanet.com.cn上面,后面连续跳转了多个广告请求,还有骗京东自家的推广点击的。在第11个请求时,被定向到了京东首页。
代理的拦截效果截图:
访问优酷,被重定向到了ye87.net
ye87.net被代理拦截重新定向到了youku
adbreak打印的重定向信息
之前预览移动页面,使用一款名为User-Agent Switcher的插件。这两天用chrome开发者工具修改设置时看到新版的chrome自带设置项可十分方便的预览移动页面。设置方法如下:
1. 打开chrome开发者工具,点右下角设置
2. 在设置页面切换到Overrides选项卡,设置User Agent和Device metrics两项即可。
还可以使用Chrome结合ADBPlugin调试安卓手机上的网页,具体信息参照:https://developers.google.com/chrome-developer-tools/docs/remote-debugging
前段时间玩了下这款游戏,个人感觉游戏在用户活跃和付费激励方面设计得很好,从一个玩家的角度来说下这款游戏。
直接上图说明
1. 主界面
游戏主界面,大家能看到界面中两个红色中间带N的圆点。这两个点会一大一小的闪动,让你非常有想点击的欲望。
2. 用户激励
2.1 每天登陆送赠送
赠送的50符石(约相当于RMB 5元价值),体力用完后可点击恢复120点体力,8.8W金币,惊喜礼包一般是南瓜花或南瓜。
1.2 点斗积分
玩家达到35级以后,可以参加战斗系统,5场全胜,可以得230符石、若干金币,5场全输可以得160符石奖励。胜利以后声望增加,可以升级爵位,可以增加体力、领导力上限,每天可领取一定数量符石。
2.3活动副本
循环活动副本,出主角卡、南瓜、小金龙。主角卡用来升级打怪,南瓜可以给主角升级,小金龙可以卖金币。
3. 用户付费激励
3.1 体力购买
用户可用体力约为120点,副本每次消耗约6-8点,每隔几分钟可以回复1点,花费符石可1次购买120点体力,没有充值过的帐号每天仅可购买1次,充值后购买次数可增加,后期升级每天需大量体力,很多用户会充值。
3.2 战斗加速
左下角的"X2"代表当前游戏进行速度,默认是X1速度非常慢。X2后游戏进行速度会加快,可节省大量时间。普通用户可以X2,充值以后可以到X3。
3.3 月卡会员赠送
充值30块,你能得到什么,300符石?再送你3000符石(人民币300元),是不是感觉很超值?充30块钱月卡,一次获得等价符石,每天再送你100符石。刺激冲动型用户的付费欲望。
4. 卡牌进化系统
卡牌进化的过程如下:
1) 白色卡牌 升到25级 一套绿装 进化到绿色
2) 绿色卡牌 升到30级 一套蓝装 进化到蓝色
3) 蓝色卡牌 升到60级 一套精英蓝 进化到金边
4) 金边卡牌 此时不升级 一张蓝色卡牌 进化到金边+1
5) 金边卡牌+1 升到65级 两张蓝色卡牌 进化到金边+2
6) 金边卡牌+2 升级到70级 一张蓝色金边卡牌 进化到金边+3
7) 金边卡牌+3 升级到75级 一张紫色金边卡牌 进化到紫色
8) 紫色卡牌 此时不升级 一套紫装 进化到紫色金边
9) 依次+1 +2 +3,后面的没玩过。
说明:75级蓝卡+3升紫色,需要的金边卡牌是需要打副本掉落,或打碎片(掉率不高,且需要集齐80-120个)兑换到紫卡,升到75级,用一套紫装升到金边。一张紫卡的成本非常高,后期+1, +2, +3需要大量紫卡,如果玩家后期想要玩下去必须要充值。
5. 不定期活动
不定期会开放各种活动,上线送金币、符石,增加活动副本次数,增加卡牌掉率。你是玩家遇上这样的机会,还不得泡在线上。体力用完了,普通帐户只能买1次怎么办?亲,考虑下掏钱吧!
6. 总结:
6.1 这款游戏在吸引用户付费方面做了很多设计,原本与人民币等价兑换的符石,在游戏中普通玩家也可大量获得。针对普通玩家,使用购买体力、加速等方式让用户掏小钱(5块15块的)。针对想深入一点的玩家,月卡只需30块就可以多得300块钱的符石。让用户付出很少的代价就可以获得极大的心理价值反馈。针对高端玩家,后期紫卡升级可是无底洞,几千上万都填不满,煤老板有地方消费了。
6.2 游戏中金币系统设计存在比较大的问题,没有一个很明显的获取方式。活动副本的小金龙掉率低,而且掉的钱很快消耗掉。大量金币基本靠活动赠送,不知是有意为之还是存在bug。后期可以减少活动赠送,在商城里加一个符石购买金币,让用户掏钱。哈哈!
6.3 因为不存在用户关系,用户基本处于单人游戏环境。当进行到后期需要大量充值情况下,游戏对玩家吸引力减弱,缺乏一个长期可持续的游戏模式。
6.4 装备系统刚出来,自己还没刷出来过,冒似没掉率很低,不知又是一个吸金大坑还是鸡肋设计。
1. 去除滚动条
aau创建webform可以去掉滚动条,但测试的时候发现如果网页中对html设置了overflow-y:scroll;滚动条还是会显示出来,页面的doctype好象也可以影响滚动条的显示。最终使用代码将所以滚动条显示出来,在截图的时候裁掉滚动条。
计算滚动条代码:
var js = /** document.documentElement.style.overflowY='scroll'; **/ wb.doScript(js); var scrollWidth = wb.document.documentElement.offsetWidth - wb.body.clientWidth;
2. 触发layzload加载的图片
很多网站对图片使用了懒加载,图片显示不全,强制设置滚动条到底部可以解决大部份情况。
js添加一行
window.scrollTo(0, 100000);
3. 多用win.delay
最开始在使用setPos修改webform的宽度之后,因为我设置的宽度大于body的宽度截图出现头部居中主体内容未居中的情况,尝试在调用setPos以后调用win.delay(20)问题就解决了。在设置scroll的值触发图片懒加载以后也需要暂停一下让图片加载完成,不过要根据实际网页的情况去设置。