参考资料
subjects
Rails 数据库迁移
Rails 运行模式
development
每次修改后,下一个请求以后都会自动生效,因为reload了code
config/environments/development.rb
# In the development environment your application's code is reloaded on
# every request. This slows down response time but is perfect for development
# since you don't have to restart the webserver when you make code changes.
config.cache_classes = false
Production
每次修改后,不会自动生效
config/environments/production.rb
# The production environment is meant for finished, "live" apps.
# Code is not reloaded between requests
config.cache_classes = true
注意到DocumentRoot和Directory是指向public這個靜态档案的目录。设定好之后,执行sudo apache2ctl restart便会启用。如果之后你的Rails有任何修改要重新载入,但是并不想把Apache重启,请在你的Rails应用程序目录下執行
touch tmp/restart.txt
即可,這样Passenger就会知道要重新载入Rails,而不需要重启Apache。
controller间 Action 调用
简单跳转
redirect_to :controller => "controller B", :action => "action b", :id => "1"
需要在一个controller A中调用controller B的action, 这里不是简简单单的redirect或者是render, 只是在逻辑上需要执行controller B的action代码,view还是由A来render, 并且A中所有的全局变量也继承到B中, 下面是解决办法:
def exeRedirect (options={})
params.merge!(options)
c = ActionController.const_get(Inflector.classify("#{params[:controller]}_controller")).new
c.process(request,response)
#如果需要当前的实例变量也由B来覆盖,那么开启下面一行, 并且在执行后需要调用return
#c.instance_variables.each {|v| self.instance_variable_set(v,c.instance_variable_get(v))}
end
#在controlelr A中定义上面的方法然后调用:
exeRedirect :controller => controllerB, :action => actionB
before_filter
before_filter :require_admin, :only => [:destroy]
before_filter :authorize, :except => [:index, :new]
script/plugin
There is no longer have a script/plugin directory Rails 3.
Rails 3 now runs commands through the "rails" script.
rails plugin install http://url/of/your/package
cookie-session
Rails2之前是把session放在服务器端
Rails2之后默认采用了在browser的cookie中保存session数据的方式,因此保存在session中的数据不能超过4K,否则会出现CookieOverflow的例外
在session中一般保存有user_id和flash的内容,在使用了protect_from_forgery后,还会保存有_csrf_token的字段。此外,可能还会有session_id的字段,但是由于session内容是保存在单独的cookie中,而不是数据库中,所以在使用cookie-session的时候,这个session_id并没有实际的意义。
session中的数据在保存在cookie中时是先marshal后,然后利用密码来加密的。假设session的内容是data,那么实际在cookie中的内容就会是如下形式
marshal(data)---digest_with_secret_key(marshal(data))
这里在加密时所用的secret key就是在config/initializer/session_store.rb中所设置的serect字段;而在该文件中设置的key字段,就是保存在browser中的cookie的名称。
protect_from_forgery
rails2.0以后的版本都会默认开启该选项(在application_controller.rb中),它会利用保存在cookie中的csrf_token字段来生成自动添加在form中的隐藏字段authenticity_token,然后利用_authenticity_token来实现CSRF的功能。
CSRF
Cross Site Reference Forgery works by including malicious code or a link in a page that accesses a web application that the user is believed to have authenticated. If the session for that web application has not timed out, an attacker may execute unauthorized commands.
helper_method
helper_method : 可以指定控制器中的某些方法为helper方法,这些方法可以直接在视图中使用。
example
application_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery
helper_method :current_user
private
def current_user
@current_user ||= User.find(session[:user_id]) if session[:user_id]
end
end
views/layouts/application.html.erb
<html>
<head>
<title>Auth</title>
<%= stylesheet_link_tag :all %>
<%= javascript_include_tag :defaults %>
<%= csrf_meta_tag %>
</head>
<body>
<div id="user_nav">
*<% if current_user %>*
*Logged in as <%= current_user.email %>.*
<%= link_to "Log out", log_out_path %>
<% else %>
<%= link_to "Sign up", sign_up_path %> or
<%= link_to "log in", log_in_path %>
<% end %>
</div>
<% flash.each do |name, msg| %>
<%= content_tag :div, msg, :id => "flash_#{name}" %>
<% end %>
<%= yield %>
</body>
</html>