Ruby on Rails 使用问题

1、 变量定义
title is a local variable. They only exists within it’s scope (current block)
@title is an instance variable - and is available to all methods within the class.
In Ruby on Rails - declaring your variables in your controller as instance variables (@title) makes them available to your view.

2、rails 中链接 redis redis
首先在 Gemfile 中 添加,gem ‘redis’, ‘3.2.2’
然后在配置文件中 config/initializers/ 目录先定义 redis_client.rb ,声明全局变量 $redis_test = Redis.new(:host => ‘10.119.104.109’, :port => 6488, :password => ‘0fbc1cbb23c7e4d3’)
即可在框架中使用,需要注意的是需要重启服务器。

3、测试环境数据同步
执行test 环境的rake 任务: rake db:migrate RAILS_ENV=test
为了让每次在development 环境下的修改能同时在 test 环境生效,可以修改 .bashrc 中增加
alias rake_db_migrate=’rake db:migrate && rake db:migrate RAILS_ENV=test’
运行测试环境:
rails s -e test -p 3001 -P /tmp/pids/test_server.pid

4、不同环境数据库切换

@user = User.find(1)

dbconfig = YAML::load(IO.read(“config/database.yml”))
ActiveRecord::Base.establish_connection(dbconfig[“test”])

params = ActionController::Parameters.new ({:user => @user.as_json})

user_params = params.require(:user).permit(:name, :age)
User.create(user_params)

– User.find_by_sql(‘replace into users (“id”, “name”, “age”) values (4, “zmingshi”, 28)’)
– User.find_or_create_by(user_params)

5、安装mongrel

安装mongrel替代webrick,遇到如下问题(ruby版本2.0.0 rails版本4.0.0)

ERROR: Error installing mongrel:
ERROR: Failed to build gem native extension.

原因在于Mongrel 1.1.5与Ruby 2.0 不兼容。可以通过安装另个版本

gem install mongrel –pre

成功安装, 在 Gemfile 中添加 gem ‘mongrel’, ‘~> 1.2.0.pre2’, bundle update 更新Gemfile.lock

即可通过 rails server mongrel 启动

6、gem 删除

remove all old versions of the gem

gem cleanup rjb

choose which ones you want to remove

gem uninstall rjb

remove version 1.1.9 only

gem uninstall rjb –version 1.1.9

remove all versions less than 1.3.4

gem uninstall rjb –version ‘<1.3.4’

Gemfile 中添加gem 不指定版本,一般最自动下载最新的,可能产生不兼容问题,也会导致gem 留存多个版本,可以考虑删除不必要的gem.

7、rails 配置 unicorn + nginx 运行环境

0) 编译静态文件
在production 环境会编译静态文件到public/assets 目录下
rake assets:clean RAILS_ENV=production
rake assets:precompile RAILS_ENV=production
这样nginx 可以直接获取静态资源文件,而无需再经过 rails 处理,有助于提高响应速度。

1) 安装unicorn 并配置
在Gemfile 文件中添加 gem ‘unicorn’, 并执行 bundle install 即可。
在config 目录下加入unicorn.rb 配置文件,内容如下(可参考官方模板):

worker_processes 1
APP_PATH = File.expand_path(“../..”, FILE)
working_directory APP_PATH

listen APP_PATH + “/tmp/sockets/unicorn.sock”, :backlog => 64

listen 8080, :tcp_nopush => true

timeout 30

pid APP_PATH + “/tmp/pids/unicorn.pid”

stderr_path APP_PATH + “/log/unicorn.stderr.log”
stdout_path APP_PATH + “/log/unicorn.stdout.log”

combine Ruby 2.0.0+ with “preload_app true” for memory savings

preload_app true

check_client_connection false

local variable to guard against running a hook multiple times

run_once = true

2) 配置nginx,内容如下:

this can be any application server, not just unicorn

upstream app_server {
server unix:/tmp/sockets/unicorn.sock fail_timeout=0;
}

server {

listen 3002;

server_name server_name_test;

keepalive_timeout 5;

root workspace/rails/appinfo/public;

try_files uri/index.html uri.html $uri @app;

location @app {

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

proxy_set_header Host $http_host;

proxy_redirect off;

proxy_pass http://app_server;

}

# Rails error pages
error_page 500 502 503 504 /500.html;
location = /500.html {
root workspace/rails/appinfo/public;
}
}

3) 启动unicorn并重启nginx

unicorn_rails -c ../appinfo/config/unicorn.rb -D -E production
sbin/nginx -s reload

注意:静态资源编译在生产环境有效,因此部署在生产环境有助于提高响应速度。

8、X-Frame-Options 设置问题

Rails 4 appears to set a default value of SAMEORIGIN for the X-Frame-Options HTTP response header. This is great for security, but it does not allow for parts of your app to be available in an iframe on a different domain.
You can override the value of X-Frame-Options globally using the config.action_dispatch.default_headers setting:
config.action_dispatch.default_headers[‘X-Frame-Options’] = “ALLOW-FROM https://apps.facebook.com”

f you want to remove the header completely, you can create an after_action filter:
class FilesController < ApplicationController
after_action :allow_iframe, only: :embed

def embed
end

private

def allow_iframe
response.headers.except! ‘X-Frame-Options’
endend
Or, of course, you can code the after_action to set the value to something different:
class FacebookController < ApplicationController
after_action :allow_facebook_iframe

private

def allow_facebook_iframe
response.headers[‘X-Frame-Options’] = ‘ALLOW-FROM https://apps.facebook.com’
endend
Note that you need to clear your cache in certain browsers (Chrome for me) while debugging this.

9、Unicorn Signal

Master Process
* HUP - reloads config file and gracefully restart all workers. If the “preload_app” directive is false (the default), then workers will also pick up any application code changes when restarted. If “preload_app” is true, then application code changes will have no effect; USR2 + QUIT (see below) must be used to load newer code in this case. When reloading the application, Gem.refresh will be called so updated code for your application can pick up newly installed RubyGems. It is not recommended that you uninstall libraries your application depends on while Unicorn is running, as respawned workers may enter a spawn loop when they fail to load an uninstalled dependency.

* INT/TERM - quick shutdown, kills all workers immediately

* QUIT - graceful shutdown, waits for workers to finish their current request before finishing.

* USR1 - reopen all logs owned by the master and all workers See Unicorn::Util.reopen_logs for what is considered a log.

* USR2 - reexecute the running binary. A separate QUIT should be sent to the original process once the child is verified to be up and running.

* WINCH - gracefully stops workers but keep the master running. This will only work for daemonized processes.

* TTIN - increment the number of worker processes by one

* TTOU - decrement the number of worker processes by one

Worker ProcessesNote: as of unicorn 4.8, the master uses a pipe to signal workers instead of kill(2) for most cases. Using signals still (and works and remains supported for external tools/libraries), however.
Sending signals directly to the worker processes should not normally be needed. If the master process is running, any exited worker will be automatically respawned.

* INT/TERM - Quick shutdown, immediately exit. Unless WINCH has been sent to the master (or the master is killed), the master process will respawn a worker to replace this one. Immediate shutdown is still triggered using kill(2) and not the internal pipe as of unicorn 4.8

* QUIT - Gracefully exit after finishing the current request. Unless WINCH has been sent to the master (or the master is killed), the master process will respawn a worker to replace this one.

* USR1 - Reopen all logs owned by the worker process. See Unicorn::Util.reopen_logs for what is considered a log. Log files are not reopened until it is done processing the current request, so multiple log lines for one request (as done by Rails) will not be split across multiple logs.

It is NOT recommended to send the USR1 signal directly to workers via “killall -USR1 unicorn” if you are using user/group-switching support in your workers. You will encounter incorrect file permissions and workers will need to be respawned. Sending USR1 to the master process first will ensure logs have the correct permissions before the master forwards the USR1 signal to workers.

Procedure to replace a running unicorn executableYou may replace a running instance of unicorn with a new one without losing any incoming connections. Doing so will reload all of your application code, Unicorn config, Ruby executable, and all libraries. The only things that will not change (due to OS limitations) are:

1. The path to the unicorn executable script. If you want to change to a different installation of Ruby, you can modify the shebang line to point to your alternative interpreter.

The procedure is exactly like that of nginx:

1. Send USR2 to the master process

2. Check your process manager or pid files to see if a new master spawned successfully. If you're using a pid file, the old process will have ".oldbin" appended to its path. You should have two master instances of unicorn running now, both of which will have workers servicing requests. Your process tree should look something like this:

unicorn master (old)
_ unicorn worker[0]
_ unicorn worker[1]
_ unicorn worker[2]
_ unicorn worker[3]
_ unicorn master
_ unicorn worker[0]
_ unicorn worker[1]
_ unicorn worker[2]
_ unicorn worker[3]

3. You can now send WINCH to the old master process so only the new workers serve requests. If your unicorn process is bound to an interactive terminal (not daemonized), you can skip this step. Step 5 will be more difficult but you can also skip it if your process is not daemonized.

4. You should now ensure that everything is running correctly with the new workers as the old workers die off.

5. If everything seems ok, then send QUIT to the old master. You're done!

If something is broken, then send HUP to the old master to reload the config and restart its workers. Then send QUIT to the new master process.

10、Rails type 字段问题

“type” is a reserved field name for single table inheritance (STI). It’s been said many times to not use the column name ‘type’, because rails uses this to define the subclass of a model that should be loaded. (great feature, by the way). It turns out that type is a Ruby core method, otherwise known as Object#type.

inheritance_column() public
Defines the column name for use with single table inheritance. Use set_inheritance_column to set a different value.

two ways to disable single table inheritance

 1、Don’t use the column name ‘type’
 2、Or if the first is no option for you: Tell Rails to look for a not existing column like:

class MyModel < ActiveRecord::Base
# disable STI
inheritance_column = :_type_disabledend
end

11、Rails datetime as_json 格式问题
config.active_support.use_standard_json_time_format:在 JSON 格式的数据中是否把日期转换成 ISO 8601 格式。默认为 true。然而rails 4.0 无法使用,故只能在 config/initialize 中创建类代替
class ActiveSupport::TimeWithZone
def as_json(options = {})
strftime(‘%Y-%m-%d %H:%M:%S’)
end
end

12、Rails 时区设置
//config/application.rb 中修改
# Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
# Run “rake -D time” for a list of tasks for finding time zone names. Default is UTC.
config.time_zone = ‘Beijing’
这个值是rails系统对显示时间的默认设置,可以通过rake time:zones:all列出所有可以设置的时区,一般来说把这个设置为Beijing。

13、Rails 修改表名称
rails generate migration ChangeAppnameInHbapps
该命令无法生成详细代码,需要手动写,如果需要支持rollback, 必须实现 down, 两种方式均可。
class ChangeAppnameInHbapps < ActiveRecord::Migration
def change
reversible do |dir|
# change_table :hbapps do |t|
# dir.up { t.change :appname, :text }
# dir.down { t.change :appname, :string }
# end
dir.up { change_column :hbapps, :appname, :text }
dir.down { change_column :hbapps, :appname, :string }
end
end
end

14、route 名称以及路由指定
<%= link_to ‘DataSync’, { :controller => :recmd_data_sync, :action => :datasync, :id => complete_page_info.id }, :method => :get, class: ‘btn btn-xs btn-success’, style: ‘width:70%’ %>
get ‘recmd_data_sync/:id’ => ‘recmd_data_sync#datasync’, as: :datasync
会生成 datasync_url 和 datasync_path, 前者有完整hostname, 后者则只带有相对的路径。

15、模型数据验证
validates :score, numericality: { only_integer: true }, 指定整数
validates :accept_prob, numericality: { :greater_than_or_equal_to => 0.1, :less_than_or_equal_to => 1.0 } 指定0-1 之间的浮点数

16、placeholder 指定-需要浏览器支持
<%= f.number_field :page_id_type, class: “form-control”, :placeholder => “0-开启全屏 1-开启半屏 2-开启后弹出” %>

17、rails 中使用bootstrap 插件

首先给它添加个几个gem。
gem “therubyracer”
gem “less-rails”
gem “twitter-bootstrap-rails”
然后,运行
bundle install

rails g scaffold product name:string price:decimal description:text
然后,继续运行以下几个命令

更新db 解构

rake db:migrate

安装bootstrap 文件 run the bootstrap generator to add Bootstrap includes into your assets

rails generate bootstrap:install

创建一个layout

rails g bootstrap:layout

创建资源模板

rails g bootstrap:themed Products
rails s 即可看到 bootstrap 风格的页面,详细文档参见: https://github.com/seyhunak/twitter-bootstrap-rails
一个可以帮助我们的项目,Bootswatch
我们在刚才的Gemfile 中,再添加两个gem:
gem ‘twitter-bootswatch-rails’
gem ‘twitter-bootswatch-rails-helpers’
在我们的项目中,运行下面的两个新命令:
rails g bootswatch:install cerulean # 安装该theme 的基础文件
rails g bootswatch:import cerulean # 导入一个线上的theme 的变量文件
注:在使用的Gem 中,会存在bug,或者,版本更新导致的Gem 不匹配, 也会引起Bug。
修改一下​​application.css中的引用:
*= require cerulean/loader
*= require cerulean/bootswatch
此时报错如下:
ActionView::Template::Error (variable @glyphiconsEotPath is undefined
(in /path-to/cerulean/loader.css.less))
注释掉 loader.css.less 中@import “twitter/bootstrap/glyphicons”; 即可, 如果要使用bootstrap 的glyphicons组件,则需要定义相关path. 可以在 app/assets/stylesheets/bootstrap_and_overrides.css.less 文件中找到相关定义,copy 此定义至 cerulean/loader.css.less 文件即可。注意:
twitter-bootstrap-rails (3.2.2)、twitter-bootswatch-rails (3.3.4.0)、therubyracer (0.12.2)
// Set correct font paths
@glyphiconsEotPath: font-url(“glyphicons-halflings-regular.eot”);
@glyphiconsEotPath_iefix: font-url(“glyphicons-halflings-regular.eot?#iefix”);
@glyphiconsWoffPath: font-url(“glyphicons-halflings-regular.woff”);
@glyphiconsTtfPath: font-url(“glyphicons-halflings-regular.ttf”);
@glyphiconsSvgPath: font-url(“glyphicons-halflings-regular.svg#glyphicons_halflingsregular”);

18、rails 中使用error message 提示
rails 中错误信息提示,是依靠application.rb 中的ActionView 实现,细节如下,

    该方法会在错误信息中一个 class="field_with_errors" 的div 元素 (label 和 input) 都会加入,定义如下,因此会改变原来的页面样式,体验较差。
     .field_with_errors {

padding: 2px;
background-color: red;
display: table; #会改变input 大小,删除即可
}
可以重写该方法只给需要的元素添加class, 创建 config/initializers/view_error_wrap.rb,内容如下:
ActionView::Base.field_error_proc = Proc.new do |html_tag, instance|
if html_tag.index ‘label’
html_tag
else

#{html_tag}
“.html_safe
#class_attr_index = html_tag.index ‘class=”’

#if class_attr_index
#  html_tag.insert class_attr_index + 7, 'field_with_errors '
#else
#  html_tag.insert html_tag.index('>'), ' class="field_with_errors"'
#end

end
end
该方法只给input 对应的添加 class 属性,可以根据需要适当定制。

  1. rails 中使用select
    rails中select 定义如下: select(object, method, choices = nil, options = {}, html_options = {}, &block)
    其中option 是select 控件定义的功能项,如::include_blank => false 等,html_options 可以用来指定 class 等html 相关属性,实例如下:
    <%= f.select :banner_click, [[‘不支持’, ‘0’], [‘支持’, ‘1’]], { :include_blank => false }, { :class => ‘form-control’ } %>

  2. rails 中使用 bootstrap3-datetimepicker-rails (4.17.37)
    github 地址:https://github.com/TrevorS/bootstrap3-datetimepicker-rails,使用方法见: http://eonasdan.github.io/bootstrap-datetimepicker/
    首先在安转相关gem , 在 Gemfile 中加入如下:
    gem ‘momentjs-rails’, ‘>= 2.9.0’
    gem ‘bootstrap3-datetimepicker-rails’, ‘~> 4.17.37’

      bundle install 之后即可。修改:   app/assets/javascripts/application.js,  增加如下:
      //= require moment
      //= require bootstrap-datetimepicker
      如果需要制定locale 可以再加入//= require moment/ , 例如: //= require moment/zh-cn, 此处datetimepicker locale 制定借用 moment的内部库,支持哪些locale 具体可见:https://github.com/moment/moment/tree/develop/locale
    

    注意:在使用该插件的时候,需要bootstrap 的字体库glyphicons 支持,因此必须保证其可用。

  3. rails 中concern 下建立帮助方法,报错 NameError (uninitialized constant GameReserveConf:: ModelHelper)

在 rails 4 中会自动创建并加载concern 下的文件:app/models/concerns、app/controllers/concerns,在模型需要帮助方法的时候只需在app/models/concerns 文件夹下创建帮助方法,必须继承ActiveSupport::Concern
module ModelHelper extend ActiveSupport::Concern
def http_get(url)
response = Net::HTTP.get_response(URI.parse(url))
code = response.code
if code == ‘200’
response.body.strip
else

end
end
end

在需要使用的model 或者 controller 中只需要 include ModelHelper即可使用,其中的帮助方法。需要注意的是,rails 约定大于配置的惯例,这个脚本文件的名称必须符合约定,即必须为:model_helper.rb,否则rails则作报错,NameError (uninitialized constant GameReserveConf:: ModelHelper). 实际是因为rails 按照默认约定,在concerns 目录下没有找到对应的文件(module)导致的错误

  1. Rails callback 回调方法

下面列出了所有可用的回调,按照各个操作触发的顺序:
创建对象

* 
    * before_validation
    * after_validation
    * before_save
    * around_save
    * before_create
    * around_create(Data insert into db)
    * after_create
    * after_save

更新对象

* 
    * before_validation
    * after_validation
    * before_save
    * around_save
    * before_update
    * around_update(Data insert into db)
    * after_update
    * after_save

销毁对象

* 
    * before_destroy
    * around_destroy
    * after_destroy

Update operations have exactly the same set, except read update instead of create everywhere (and UPDATE instead of INSERT).
From this, you can see that validation is carried out before the before_save and before_create callbacks.
The before_save occurs slightly before the before_create. To the best of my knowledge, nothing happens between them; but before_save will also fire on Update operations, while before_create will only fire on Creates.
回调实例如下:
class User < ActiveRecord::Base
validates :login, :email, presence: true

before_validation :ensure_login_has_a_value

before_create do
self.name = login.capitalize if name.blank?
end

protected
def ensure_login_has_a_value
if login.nil?
self.login = email unless email.blank?
end
end
end

  1. ActiveRecord::Dirty

    该模块可以用来记录跟踪每个record 的数据状态,是否修改以及修改前后的内容。不过在未来的新版本可能会被遗弃或者移动到别的模块。具体使用方法如下:
    A newly instantiated object is unchanged:
    person = Person.find_by_name(‘uncle bob’)
    person.changed? # => false
    Change the name:
    person.name = ‘Bob’
    person.changed? # => true
    person.name_changed? # => true
    person.name_was # => ‘uncle bob’
    person.name_change # => [‘uncle bob’, ‘Bob’]
    person.name = ‘Bill’
    person.name_change # => [‘uncle bob’, ‘Bill’]
    Save the changes:
    person.save
    person.changed? # => false
    person.name_changed? # => false
    Assigning the same value leaves the attribute unchanged:
    person.name = ‘Bill’
    person.name_changed? # => false
    person.name_change # => nil
    Which attributes have changed?
    person.name = ‘bob’
    person.changed # => [‘name’]
    person.changes # => { ‘name’ => [‘Bill’, ‘bob’] }
    Before modifying an attribute in-place:
    person.name_will_change!
    person.name << ‘by’
    person.name_change # => [‘uncle bob’, ‘uncle bobby’]
    Constants
    DIRTY_SUFFIXES = [‘_changed?’, ‘_change’, ‘_will_change!’, ‘_was’]

24、Rails 国际化i18n
修改config/locales/en.bootstrap.yml文件,可以将英文字段显示标签,改成中文:
titles:
edit: “Edit %{model}”
save: “Save %{model}”
new: “New %{model}”
delete: “Delete %{model}”
label:
game_reserve_conf:
app_name: ‘名称’
game_type: ‘类型’
rec_rank: ‘级别’
fp_time: ‘时间’
activerecord:
attributes:
game_reserve_conf:
app_name: ‘名称’
game_type: ‘类型’
rec_rank: ‘级别’

其中label 是show 时候的名称, activerecord 下边是表单状态下的数据内容。

25、Rails Gemfile 不同项目版本不同,导致unicorn 启动失败
错误提示信息: You have already activated unicorn 5.1.0, but your Gemfile requires unicorn 5.0.1. Prepending bundle exec to your command may solve this. (Gem::LoadError)
可以通过如下命令执行:
bundle exec unicorn_rails -c ../commercial/config/unicorn.rb -D -E production

26、Rails Json API: Can’t verify CSRF token authenticity
错误提示信息: Can’t verify CSRF token authenticity
修改app/controllers/application_controller.rb 如下:
skip_before_filter :verify_authenticity_token, :if => Proc.new { |c| c.request.format == ‘application/json’ }
27、ActionController::Parameters 使用
params = ActionController::Parameters.new({person: { name: ‘Francesco’, age: 22, role: ‘admin’ } })
permitted = params.require(:person).permit(:name, :age)
其中ActionController::Parameters 可以从一个hash 中构造一个对象,从而指定和限制输入数据属性白名单,防止错误数据注入。

你可能感兴趣的:(Rails)