Ruby中的小问题,放在这里备查。
0、
打出当前调用栈: puts caller
1、
ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken)
原理是rails为了防止伪造当前web程序的链接,技术上是嵌入一个随机字符串在会话中,这样攻击者无法知道,保证了不会有通过其他网站控制器从CSRF的攻击行动。
解决方法是为请求加一个参数:参数名是<%=request_forgery_protection_token.to_s%>,值是<%=form_authenticity_token.to_s%>
若用form提交,可在form中加入
<%= tag(:input, :type => "hidden", :name => request_forgery_protection_token.to_s, :value => form_authenticity_token) %>
若用ajax提交,可在参数中加入"<%=request_forgery_protection_token.to_s%>=<%=form_authenticity_token.to_s%>"
2、
在controller中使用Thread.current[:some_key] = 'some value'时,可能会引发严重的数据和权限问题,解决办法是after_filter中Thread.current[:some_key] = nil
3、
从GET请求的url中获取参数:
params = HashWithIndifferentAccess.new Rack::Utils.parse_nested_query("a=1&b=2") # => {"a"=>"1", "b"=>"2"}
Rails中间件中获取请求参数:
params = {}
params = params.merge(env["rack.request.query_hash"]) if env["rack.request.query_hash"].present? # 来自url
params = params.merge(env['rack.request.form_hash']) if env['rack.request.form_hash'].present? # 来自post请求
params = params.merge(env["action_dispatch.request.request_parameters"]) if env["action_dispatch.request.request_parameters"].present? # 来自post请求,并且contentType: "application/json"
4、
输出cookies:
logger.debug cookies.instance_variable_get(:@cookies).to_s
Rails的session验证机制
_session, ver = _session_id.split('--')
_session = CGI::unescape(_session)
#==========active_support/message_verifier.rb
generate_digest = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.const_get('SHA1').new, secret, _session)
unless ver == generate_digest
raise ActiveSupport::MessageVerifier::InvalidSignature
end
cookie中的_session_id在rails后台转变成session
Marshal.load(Base64.decode64("_session_id"))
5、
windows.office2010生成的xlsx文件作为附件,用rails发送email,会出现exception:
"exception"=>"ArgumentError", "error"=>"invalid byte sequence in UTF-8"
/home/zzq/.rvm/gems/ruby-1.9.2-p320/gems/activesupport-3.2.2/lib/active_support/core_ext/object/blank.rb:105:in `=~'
/home/zzq/.rvm/gems/ruby-1.9.2-p320/gems/activesupport-3.2.2/lib/active_support/core_ext/object/blank.rb:105:in `!~'
/home/zzq/.rvm/gems/ruby-1.9.2-p320/gems/activesupport-3.2.2/lib/active_support/core_ext/object/blank.rb:105:in `blank?'
/home/zzq/.rvm/gems/ruby-1.9.2-p320/gems/mail-2.4.4/lib/mail/body.rb:36:in `initialize'
/home/zzq/.rvm/gems/ruby-1.9.2-p320/gems/mail-2.4.4/lib/mail/message.rb:1909:in `new'
/home/zzq/.rvm/gems/ruby-1.9.2-p320/gems/mail-2.4.4/lib/mail/message.rb:1909:in `process_body_raw'
/home/zzq/.rvm/gems/ruby-1.9.2-p320/gems/mail-2.4.4/lib/mail/message.rb:1155:in `body'
/home/zzq/.rvm/gems/ruby-1.9.2-p320/gems/mail-2.4.4/lib/mail/message.rb:2000:in `init_with_hash'
/home/zzq/.rvm/gems/ruby-1.9.2-p320/gems/mail-2.4.4/lib/mail/message.rb:123:in `initialize'
/home/zzq/.rvm/gems/ruby-1.9.2-p320/gems/mail-2.4.4/lib/mail/attachments_list.rb:78:in `new'
/home/zzq/.rvm/gems/ruby-1.9.2-p320/gems/mail-2.4.4/lib/mail/attachments_list.rb:78:in `[]='
出错行如下:
attachments[filename] = File.read(filepath)
解决办法:
attachments[filename] = {:content => File.read(filepath, :mode => 'rb'), :transfer_encoding => :binary}
6、
mysql5.5前不支持utf8mb4,mb4字符不会出现在数据库中,为了解决这个问题,将mysql升级后,rails中生成json还有问题。
解决办法:增加文件:config/initializers/active_support_encoding.rb
内容:
module ActiveSupport::JSON::Encoding
class << self
def escape(string)
if string.respond_to?(:force_encoding)
string = string.encode(::Encoding::UTF_8, :undef => :replace).force_encoding(::Encoding::BINARY)
end
json = string.gsub(escape_regex) { |s| ESCAPED_CHARS[s] }
json = %("#{json}")
json.force_encoding(::Encoding::UTF_8) if json.respond_to?(:force_encoding)
json
end
end
end
7、
如何使用X-Accel_Redirect?
X-Accel_Redirect是nginx的功能,可以支持从文件系统直接读取文件发送到客户端,跳过应用服务器,提高效率。
在nginx配置中加入:http{server{
location /file-internal {
internal;#只接收内部请求,防止外部请求直接访问
alias /your/file/path;
}
}}
在下载action中,不用send_file,用这一句:
return head(:x_accel_redirect => '/file-internal/1.jpg',:content_disposition => "attachment; filename=\"1.jpg\"",'Content-Type'=>'image/jpeg')
nginx收到后,会将/your/file/path/1.jpg发送给客户端。
8、
使用mongoid时,在rails console中输出数据库查询语句:
Mongoid.logger.instance_variable_set('@log', $stdout)
9、
遍历文件夹:
1).仅遍历当前文件夹
Dir.foreach('/tmp') do |filename|
if filename != "." and filename != ".."
2). 遍历所有子孙文件夹
require 'find'
Find.find("/tmp") do |filename|
File.directory?(filename)
3). 批量修改文件编码
utf8转gbk:
require 'find'
arr = ["path"]
arr.each do |rep|
Find.find("D:\\apps\\#{rep}") do |filename|
if !File.directory?(filename) && (filename.ends_with?('.txt'))
f1 = File.open(filename, 'r')
s1 = f1.read
f1.close
#s2 = s1.encode('utf-8','gbk',{:invalid => :replace, :undef => :replace, :replace => '?'})
s2 = s1.encode('gbk','utf-8')
f2 = File.open(filename, 'w:gbk')
f2.puts s2
f2.close
end
end
end
10、
字符串转换为url参数:
ERB::Util.url_encode("@/\\") #=> "%40%2F%5C"
URI.encode("@/\\") #=> "@/%5C"
URI.decode("%40%2F%5C"
) #=> "@/\\"
11、
linux下生成的csv在windows下office excel乱码问题:
csv_bom = "\377\376"
filename = 'test.csv'
file = File.open(filename, 'w')
file.write csv_bom
file.close
file = File.open(filename, "a:UTF-16LE")
file.puts "列一\t列二"
file.puts "1\t2"
file.close
12、
ie中下载文件乱码,chrome、firefox不乱码问题:
user_agent = request.env['HTTP_USER_AGENT'].downcase
_filename = user_agent.include?("msie") ? ERB::Util.url_encode(File.basename(filename)) : File.basename(filename)
send_file(filename, :filename => _filename)
13、
在linux上用zip生成.zip文件,在windows上用winzip解压后,文件名乱码问题。(用好压解压不乱码)
原因是linux上的zip压缩时没有标明文件名编码,默认是UTF-8,而winzip默认为ANSI。
解决办法:
1、安装7z,sudo apt-get install p7zip-full
2、压缩命令由原(zip -r zip.zip *),修改为新(7z a -r -t7z 7z.zip *)
参考:http://frank19900731.github.io/blog/2015/02/11/jie-jue-mac-xia-zip-ya-suo-wen-jian-zai-windows-xia-xian-shi-luan-ma-de-wen-ti/
14、
arr=str.scan(/[0-9]{18}/)