启动项目:
ruby script/server -e development(默认)
ruby script/server -e test
ruby script/server -e production
在编写ruby代码时,如果要引用另一个文件中的类和模块,需要使用require关键字,但是当我们在rails中引用另一个文件中的类和模块时,rails会自动把类名称根据命名约定改为文件名,然后在同一目录下加载该文件。
按模块组织控制器:
ruby script/generate controller Admin::Book action1 action2
admin模块下的book_controller控制器
Rails给Enumerable类扩展的方法
1》 group_by: 将一个对象集合分组,针对每个对象调用块,然后根据代码块的返回值作为分组的键,值是所有拥有同一个键的对象组成的数组。
eg:
User.all.group_by{|user| user.sex}
User.all.group_by(&:name)
2》 sum: 对集合进行加总,把每个元素传递给一个代码块,并对代码块返回的值进行累加。
User.all.sum(&:id) 返回所有user对象的id的和
3》 in_groups_of(arg1, arg2) 将某一个数组分为子元素由arg1个元素组合的数组元素组成的数组,出现无法填充的值由arg2填补。
eg:
[1,2,3,4,5].in_groups_of(2,"blank") =>
[[1,2],[3,4],[5,"blank"]]
字符串扩展
str[0] 第一个字符的Ascill码。
str[2..3] 返回字符串的第三个字符开始的3个字符组成的字符串。
str.at(0) 第一个字符
str.to(4) 前5个字符组成的字符串
str.from(4) 最后5个字符组成的字符串
str.first
str.last
str.starts_with?(字符串)
str.ends_with?(字符串)
str.each_char{|char| char.upcase}
str.pluralize 复数形式
str.singularize 单数形式
str.humanize
str.titleize
对数值的扩展:
figure.ordinalize 返回数字的序数形式
figure.bytes、kilobytes、megabytes、gigabytes、terabytes、
perabytes、exabyte 数据大小
figure.seconds、minutes、hours、days、weeks、fortnights、months、years 时间
注意: ago、 until、 from_now、 since
eg:
1.day.ago
1.day.ago(Time.now)
时间和日期的扩展
now = Time.now
now.to_s(:short)、to_s(:db)、to_s(:long)、to_s(:rfc822)
now.ago(2.days)、since(2.days)
change(:hour => 12) 改变日期的hour为12
advance(:hour => 12) 推迟日期的12hour
to_date、to_time
at_beginning_of_week、at_beginning_of_month、at_beginning_of_quarter(季)、at_beginning_of_year
ruby符号的扩展:
posts.group_by{|post| post.author_id}
posts.group_by(&:author_id)
with_options的使用:
Rails里有些方法使用一个Hash作为最后一个可选的参数,如果对多个方法有同样的选项,我们可以使用with_options来减少冗余:
eg:
with_options :if => :should_validate_password? do |user|
user.validates_presence_of :password
user.validates_confirmation_for :password
user.validates_format_of :password, :with => /^[^\s]+$/
end
迁移任务:
create_table
:force => true 如果表存在,强制删除,然后再创建表
:temporary => true 创建一张临时表,程序与数据库断开链接,则表被删除。
:options => "xxxx" 指定针对于底层数据库的选项,这些选项会被加到create table语句的后面
:primary_key 主键
:id => false 没有主键的表
如果迁移任务 提供的方法 不够满足你 的需要,也 可以使用数 据库专有的 功能:使用execute() 方法就可以运行原生 SQL 语句。例如:给表加上外键
class CreateLineItems < ActiveRecord::Migration
def self.up
create_table :line_items do |t|
t.column :product_id, :integer
t.columnrder_id, :integer
end
execute "alter table line_items
add constraint fk_line_item_products
foreign key (product_id) references products(id)"
end
def self.down
drop_table :line_items
end
end
ActiveRecord::Base
column_names 属性组成的数组
columns_hash["属性名称"] 属性名称信息
属性_before_type_cast 读取属性时,ActiveRecod会尽量将得到的值转型成适当的ruby类型,如果我们希望的到属性的原始值,可以在属性名称后面加上before_type_cast。
eg:User.first.created_at => 2010-06-24 09:41:17
连接数据库: ActiveRecord::Base.establish_connection(:adapter => "mysql", :host => "localhost", :database => "rails", :username => "root", :password => "1234")
防止恶意注入:
1> 问号占位符: User.find(:all, :conditions => ["id > ?", 3]
2> 命名占位符: User.find(:all, :conditions => ["id > :id", {:id => 3}])
注意:
命名占位符的语句可以转换为
User.find(:all, :conditions => ["id > :id", params[:user]])
获取字段统计信息:
average:
maximum:
minimum:
sum :
count :
以上方法的参数:
:conditions、:joins、:limit、:order、:having、:select、 :distinct
eg:
Order.maximum :amount, :group => "state", :limit => 3,rder => "max(amount) desc"
拥有订单最大的三个州
更新操作:
update_attribute、update_attributes、update、update_all
创建操作:
create、create!、save、save!
删除数据:
delete、delete_all、destroy、destroy_all
delete绕过了ActiveRecord的回调和验证,destory没有绕过回调和验证
序列化数据:
serialize :属性
序列化的属性可以直接存入Array和hash类型的数据,也可以直接读出来使用
缺点:
ruby应用之外的应用访问序列化的数据时,除非它能够理解yaml格式,否则无法获取这个字段的信息。
弥补这种缺点的方式是用对象聚合的方式来实现类似的效果
聚合/组合:
聚合可以把一个或多个属性封装为一个类,然后这个类里可以添加操作属性的方法,这样我们就可以实现序列化所要实现的目的了,而且可以避免序列化的缺点。
composed_of :attr_name, :class_name => 类名称, :mapping => [字段与属性组成的数组]
eg:
class Xingxi < ActiveRecord::Base
composed_of :inf, :class_name => "Inf", :mapping => [[:name, :name], [:phone, :phone]]
end
class Inf
attr_reader :name, :phone
def initialize(name, phone)
@name = name
@phone = phone
end
def to_s
[@name, @phone].compact.join(" ")
end
end
inf = Inf.new("zcy", "12344454")
Xingxi.create(:inf => inf)
注意:
教程上指出 :class_name对应的“类名称”可以是类常量,也可以是包含类常量的字符串,但实际上只能是包含类常量的字符串,如果类名恰好是属性名的混合大写形式,那么class_name可以省略,但是实际上不可以,包括:mapping也不可以。
关联:
class Line < ActiveRecord::Base
belongs_to :product
end
belongs_to :product 会产生以下方法
1>:product(force_reload=false) 返回关联的product对象,默认情况下product对象会被缓存,当force_reload=true时,将重新查询数据库。
2>:product=: line对象和product对象关联起来,将line记录的外键值设为product的主键值,如果product没有保存,line保存的时候会保存product,包括外键。
3>:build_product(attributes={}) 新建一个product对象,用指定的属性对其初始化,相当于product=Product.new(attributes)。
4>:build_create(attributes={}) 创建一个product对象,与line关联,保存product对象。
order: has_one中也有order,主要用于例如最后一个***,此时便可以用order指定排序。
:dependent :destroy(true)、:nullify、 false
:destroy 删除记录的同时也删除子记录
:nullify 删除记录的同时删除子记录的外键
false 只删除记录
has_many :lines
class Product < ActiveRecord::Base
has_many :lines
end
has_many :lines 会产生以下方法
lines(force_reload=false) 同上
lines.build(attributes = {})
lines.create(attributes = {})
lines << line 将当前line对象添加到lines对象数组里
lines.push(line对象) line对象添加到lines
lines.delete(line,...) 删除一个或多个line对象,如果关联为:destroy => :destroy,子对象被删除,否则只是删除子对象的外键,打断与父对象的关联。
lines.delete_all 调用所有子对象的delete方法
lines.destroy_all 调用所有子对象的destroy方法
lines.clear 和delete一样,不同的是clear针对的是所有的子对象。
lines.find(options)
lines.count(options)
lines.size
lines.length 强制加载所有子对象,返回对象的集合。
lines.empty?
lines.replace(line对象数组) line对象数组替换原先的lines
lines.sum(options) 不便利内存中的子对象集合,直接在数据库端操作
lines.uniq 返回一个数组,包含所有具备独立id的子对象
1> finder_sql: 重新定义了统计子记录的sql语句
counter_sql: 重新定义了统计子记录的数目
注意: 如果指定了finder_sql而没有指定counter_sql,finder_sql中的子句会被替换为select count(*),然后记录子记录的数量。
eg:
has_manyingxis, :finder_sql => "select x.* from xingxis x, infos i where x.info_id = i.id and x.id > 4"
作用: 当:conditions无法满足时,:finder_sql显的非常重要。
:order : 以特定的顺序排列
:conditions : 返回符合条件的子记录
:dependent :destroy、:nullify、 false
:destroy 删除记录的同时也删除子记录
:nullify 删除记录的同时删除子记录的外键
false 只删除记录
多对多的关联有两种
1: 利用默认的关联表
2:自己创建关联表,利用关联中的:through
:through 告诉rails通过guanlians表来导航关联
:source 用来指定关联在那个属性上
:uniq => true 去掉重复的对象 等同于 :select => "distinct books.*"
eg:
class Kind < ActiveRecord::Base
has_many :guanlians
has_many :readers, :through => :guanlians, :source => :book
end
注意:
has_many :reader1s,:conditions => "guanlians.cishu > 0"
当使用conditions不能很好的表达时,无法提供参数,可以考虑以下格式,而且当同样的方法被多次调用时,可以将方法写在模块中,然后在关联中:extend => "模块名称" 来调用。
has_many :readers do
def reader(limit = 3)
find(:all, :limit => limit)
end
end
单表继承:
优点: 这样做的好处是提高读取表的速度,因为没有关联,只有一个表。
缺点: 当各个子类的相似的地方很少的时候,会导致表中有很多属性,这样处理这个问题的方法是用多态关联。
多态关联:
types表中的多态外键如果是duotai,那么表的属性是duotai_id, duotai_type,一个记录键值,一个记录类名。
class Article < ActiveRecord::Base
has_one :type, :as => :duotai
end
class Image < ActiveRecord::Base
has_one :type, :as => :duotai
end
class Type < ActiveRecord::Base
belongs_to :duotai, :polymorphic => true
end
自引用的连接:
class Employee < ActiveRecord::Base
belongs_to :boss, :class_name => "Employee", :foreign_key => :employee_id
end
预先读取子记录
以下实例如果没有:include => :people, infos为n, 那么他将执行2n+1次,如果指定了:include,将预加载与info有关的people记录,此时将提高效率,但是如果预加载了数据,但没有用这些数据,反而会降低效率。
Benchmark.bm() do |x|
x.report{
infos = Info.find(:all, :include => :people)
infos.each do |info|
info.people.name
end
}
end
如果一个对象刚刚创建出来,还没有与数据库记录建立映射,我们称它为新对象(new records)。调用new_records?
模型验证:
validate、 validate_on_create、 validate_on_update
ActiveRecord::Errors
[] info.errors[:email]
on info.errors.on(:email)
add(:属性, 信息)
size、length、count
each、each_error 迭代错误属性和错误属性对应的信息
each_full 迭代错误信息
full_messages 错误信息组成的数组
invalid?(属性) 如果属性无效,则返回true
to_xml
empty?
ActiveRecord::Errors.default_error_messages 这个返回所有的默认信息,如果修改默认信息的话,可以从这里修改。
回调:
创建方式
1:直接在回调中写代码。
2:声明回调处理器,处理器可以是一个代码块也可以是一个方法,如果用方法作为一个处理器,应该被声明为private或protected。
eg
def before_save
...
end
before_save :check
private
def check
end
注意:以下方法将跳过回调
* decrement
* decrement_counter
* delete
* delete_all
* find_by_sql
* increment
* increment_counter
* toggle
* update_all
* update_counters
ActiveRecord::Base
column_names: 所有列名组成的数组
columns: 所有包含列信息的对象组成的数组。
columns_hash: 列名与列对象组成的hash数组。
实例方法:
attributes: 所有属性和属性值组成的hash数组。
attributes=
attribute_names: 所有属性组成的数组。
attribute_present?(属性名称) 如果属性名称存在,则返回true,反之亦然。
事务: 要么全部执行,要么全部不执行。
模型类.transaction do
end
begin ... rescue ...end
eg:
class Info < ActiveRecord::Base
def validate
errors.add(:age, "age is not less than 0") if age < 0
end
def jian(i)
self.money = self.money - i
self.save!
end
end
info = Info.create!(:money => 100)
begin
Info.transaction do; info.jian(200); end
rescue
end
puts info.money =》 -100
该实例中要求money不能小于0,而我们也做到了,表中的数据不会被改,但是info.money 返回的值是-100,模型对象的值被该变了,这是因为ActiveRecord没有跟综对象在事务前后的状态,我们可以指定事务跟踪哪些模型对象。
Info.transaction(info) do; .... end,此时输出的值就是100了。
路由:
map.connect 重要参数
:requirements => {:name => /regexp/} 要求url中特定的组成部分与指定的正则表达式一一匹配。
:defaults => {:name => "value", ...} 设定各组成部分的默认值
:conditions => {:name => /regexp/orstring,...} 设定路由的条件
:name => value 设定:name参数的默认值
eg:
map.connect 'infos/:year', :controller => "infos", :action => "hello", :defaults => {:year => 2008},:requirements => {:year => /(19|20)\d\d/}, :conditions => {:method => :get}
注意:
map.connect "*aa", :controller => "", :action => ""
符合任何的url格式,但是一定要注意的是要放在最后,否则其他的路由都无法匹配了。
有名路由
map.hello "hello/:id", :controller => "infos", :action => "index"
1> hello_url(:id => 1)或hello_url :controller => "infos", :action => "index"
可以访问这个url。
注意: 以上url可以用path替代。
2> 地址栏中可以输入hello访问这个url。
资源路由:
map.resources :articles, :collection => {:recent => :get}, :member => {:release => :put}, :new => {:hello => :get}
增加以下规则:
recent_articles_path
release_article_path(:id => 1)
hello_new_article_path
map.resources :articles do |article|
article.resources :comments
end
articles/99/comments/4
控制器环境(可以在action中直接引用)
controller_name: controller名称
action_name: action名称
session: session
cookies: cookie
params: 存放着参数的hash对象
rsponse
request: 进入控制器的请求对象,包含属性。
domain: 请求地址域名部分的最后两端。
remote_ip: 客户端的ip地址。
env: 返回请求的环境。
get?、post?、put?、delete?、head?
method: 返回客户端访问所使用的请求方法。
xhr?或xml_http_request? 如果请求来自AJAX的辅助方法,则返回true,否则返回false。
控制器应答:
1:渲染一个模板,最常见的(.html、 .rxml、 .rjs)。
2:返回一个字符串给浏览器,主要用于发送错误提示。
3:发送html以外的数据,这种方式通常用于提供下载。
控制器每次只响应一个请求:
render、 redirect_to、 send_xxx
1> render :action
2> render :template
3> render :file
4> render :partial 调用局部模板
:object 指定传递给局部模板的对象。
5> renderml
6> render :nothing
7> render :inline
8> render :text
9> render(:update) do |page| ... end
重要参数:
:locals => {},指定模板要使用的局部变量。
:layout => false|nil|true|模板名称。
render_to_string 可以当作render使用,不过它不会跳转,只会把整个的内容作为字符串返回。
method_missing:调用指定的action名称无效时,method_missing会渲染一个内联的模板,将action的名称和请求参数显示出来。
eg:
def method_missing(name, *args)
render(:inline => %{<h2> Unknown action: #{name}</h2>
Here are the request parameters:<br/>
<%= debug(params) %>})
end
send_data(data, options) 发送一个数据流给客户端。
参数:
:filename、 disposition(inline|attachment)、status、type
send_file(path, options) 发送一个文件给客户端
参数:
:filename、 :disposition、 :status、 :type、 buffer_size、 stream
重定向:
redirect_to(:action => "")
redirect_to(path)
redirect_to(:back) 返回上一页,注意:如果redirect_to(:back)写在了index的action中,并且访问index的时候能够直接运行redirect_to(:back),则不能直接访问index的action,因为他会跳转上一页,但是没有上一页。
过滤器:
prepend_before_filter
before_filter、append_before_filter
prepend_after_filter
after_filter、append_before_filter
参数:
:only、 :except
定义过滤器的方式:
1:
before_filter do
...
end
2:
before_filter :hello,nly => [:show, :index]
skip_filter、 skip_before_filter、skip_after_filter
参数:
:only、 :except
缓存:
片段缓存、 页面缓存、 action缓存
caches_page、 caches_action、 cache do .... end
默认配置下,cache只有在产品环境下才生效,如果要在开发环境下生效,要配置以下信息中的一条。(config/environments/development.rb)
ActionController::Base.perform_caching = true|false
config.action_controller.perform_caching = true
解除缓存:
expire_action、 expire_page、 expire_fragment :controller => "...", :action => "..."
1》默认:缓存片段的名字取决于渲染该页面的控制器名称和action名称,所以使用expire_fragment指定控制器名称和action名称来是对应的片段缓存失效。
2》指定缓存名称(等同于url_for的参数)
缓存存储机制的全局设置(environment.rb设置):
缓存目录:
config.action_controller.page_cache_directory = RAILS_ROOT + "/public/caches"
缓存类型:
config.action_controller.page_cache_extension = ".html"
缺点:导致大量的数据从网络驱动器传输到某一台具体的web服务器,然后将这些数据发送给用户,所以,如果在高吐量的网站中使用这种存储机制,服务器之间的网络宽带应该非常宽。
缓存存储体系只对action缓存和片段有效,全页面缓存必须以文件的形式放在public目录下。
页面缓存是最快速的一种缓存应用。那么应该在什么时候使用他呢?
1、对于所有用户都相同的页面
2、公开的页面,没有用户认证的页面
缓存分页:
因为页面缓存的时候会忽略掉像/blog /list?page=2这样的参数,所以你需要使用/blog/list/2这样的地址形式,而原来我们使用的是id保存参数值,现在我们需要用 page来保存参数值。
下面我们修改 /config/routes.rb文件
map.connect 'blog/list/:page',
:controller => 'blog',
:action => 'list',
:requirements => { :page => /\d+/},
:page => nil
使用了新的routes定义,我们的连接也应该改成
<%= link_to "Next Page", :controller => 'blog', :action => 'list', :page => 2 %>
最终的连接结果是"/blog/list/2",当我们点这个连接的时候,后台会处理两件事情
1、应用将2放入page这个参数中,而不是原来id这个参数
2、缓存将生成 /public/blog/list/2.html 这个页面
所以,缓存分页,就要将页面参数变成页面的一部分,而不要使用地址参数的形式,他是会被忽略的。
解决危险链接的方式:
1:使用表单和按钮(button_to)
2:使用确认页面
link_to、link_to_if、link_to_unless、button_to
stylesheet_link_tag
javascript_include_tag: 假设文件在public/javascripts目录
对象调用属性:
eg: info.name 或 info["name"]
form_for、 form_tag
form_for(:info, @info, :url => {:action => "create"}, :html => {:method => "post"}
:info 告诉rails正在操作哪个模型类的对象
@info 通过哪个实例变量获得该对象
:url 访问的action地址
:html 定义访问的方法,可以定义:multipart => true,上传。
select标签:
1>collection_select(:post, :author_id, Author.all, :id, :name_with_initial, {:prompt => true})
2>select、select_tag "people", "<option>David</option>"
3>options_from_collection_for_select(@people, 'id', 'name')
4>options_for_select({ "Basic" => "$20", "Plus" => "$40" }, "$40")
子表单:
<% fields_for :name, @info.name do |field| %>
Name: <%= field.text_field :name %>
<% end %>
卸载layout页面中:
<% content_for :head do %>
<ul><li>a</li><li>b</li></ul>
<% end %>
<%= yield :head %>
发送邮件:
config.action_mailer.delivery_method = :smtp|:sendmail|:test
开发环境下默认的设置是:smtp。
:smtp、:sendmail 可以让ActionMailer发送邮件。
:test 可以用于单元测试和功能测试,电子邮件不会发送出去,而是被放入一个数组。
禁止开发环境下发送邮件:
config/environments/development.rb中设置config.action_mailer.delivery_method = :test
config.action_mailer.perform_deliveries = true|false
perform_deliveries为true,邮件被正常发送,否则不发送,用于测试。
config.action_mailer.raise_delivery_errors = true|false
设置邮件发送过程中的异常是否抛还给应用程序。false为忽略,true为抛还。
config.action_mailer.default_charset = "utf-8"
设置发送邮件的字符集。
ActionMailer::Base.smtp_settings = {
:address => "smtp.163.com",:port => 25,:domain => ".com", :authentication => :login,:user_name => "zhangcaiyan0123@163.com",:password => "zhangcaiyan",}
设置smtp服务器(其中domain是域名称)
ruby script/generate mailer OrderMailer confirm sent
模型中定义方法:
def confirm(sent_at = Time.now)
subject '标题'
recipients "zhangcaiyanbeyond@gmail.com"
from 'zhangcaiyan0123@163.com'
sent_on sent_at
body "邮件正文"
end
bcc 暗送
cc 抄送
charset 默认为smtp_settings中的default_charset属性
subject 标题
from 发件人的邮箱
recipients 收件人的邮箱
body 正文
send_on 发送时间
headers 指定邮件的头信息
attachment(上传插件) :filename => 文件名称, :body => 文件内容(file.read), :content_type => "内容类型"
OrderMailer.deliver_confirm 发送邮件
email = OrderMailer.create_confirm 创建邮件对象(TMail::Mail对象)
OrderMailer.deliver(email)
注意: OrderMailer是模型类,create_confirm中的create是表示要创建对象,confirm是表示模型类中的方法,deliver表示要发送邮件。
保护rails应用:
防御sql注入攻击:
eg:这个实例就是恶意注入的例子,其中1为true,他会查处表中的所有数据。
Core::User.find(:all, :conditions => "id > '' or 1")
防止恶意注入:
绝对不要用ruby的#{...}机制直接把字符串插入到sql语句中,而应该用Rails提供的变量绑定。
eg:
Core::User.find(:all, :conditions => ["id > ?", 3])
Core::User.find(:all, :conditions => ["id > :id", {:id => 3}])
用参数直接创建记录:
User.create(params[:user])
为了防止用户模拟一些属性提交,我们可以将某些属性保护起来。
attr_protected :属性1, :属性2 列出被保护的属性
attr_accessible :属性1, :属性2 列出允许自动赋值的属性,也就是说除此之外的都是被保护的属性
被保护的属性也就是不能通过create(params[:user])直接保存,而是需要通过赋值才可以。eg:
user = User.new
user.role = params[:role]
user.save
不要相信ID参数:
当我们通过id查找出数据,然后对数据进行操作时,我们要注意某些情况:例如当我们浏览(/show/id)某个用户的数据时,可以利用url浏览其他用户的数据,为了防止这样的事发生,可以这样:
eg:
1》 order = Order.find(params[:id], :conditions => ["user_id = ?", user_id])
2》 order = @user.orders.find(id)
3》 order = @user.orders.find(id).destroy
防御XSS攻击:
攻击者把自己编写的javascript脚本放进网页,来获得他们想要的cookie,我们可以通过rails提供的h(string)辅助方法(实际上是html_escape()方法的别名)
生成rails项目的HTML文档
rake doc:app
ActiveRecord::Errors.default_error_messages = hash
修改默认错误显示信息
named_scope的使用:
named_scope :quanbu, :conditions => ["name=zcy"]
named_scopeianzhi, :lambda{|limit|{:limit = limit}}
Shili.quanbu.xianzhi(3)
显示错误页面: 当指定的异常发生时,将显示特定的页面,这个最好放到application_controller中
rescue_from 异常, :with => :action
eg:
rescue_from Exception, :with => :error
def error
render :file => "novel/infos/error", :layout => "novel"
end
对于boolean类型的数据,应该省略前面的is_,ActiveRecord会自动加个?号,映射成actived? ,不是boolean型的数据也会也会扩展?
_form下的共享表单,区间的情况
1:map.namespace :doctor do |doctor|
doctor.resources :patients
end
["doctor", @patient ]
2:map.resources :doctor do |doctor|
doctor.resources :patients
end
[@doctor, @patient ]
ruby script/server -e development(默认)
ruby script/server -e test
ruby script/server -e production
在编写ruby代码时,如果要引用另一个文件中的类和模块,需要使用require关键字,但是当我们在rails中引用另一个文件中的类和模块时,rails会自动把类名称根据命名约定改为文件名,然后在同一目录下加载该文件。
按模块组织控制器:
ruby script/generate controller Admin::Book action1 action2
admin模块下的book_controller控制器
Rails给Enumerable类扩展的方法
1》 group_by: 将一个对象集合分组,针对每个对象调用块,然后根据代码块的返回值作为分组的键,值是所有拥有同一个键的对象组成的数组。
eg:
User.all.group_by{|user| user.sex}
User.all.group_by(&:name)
2》 sum: 对集合进行加总,把每个元素传递给一个代码块,并对代码块返回的值进行累加。
User.all.sum(&:id) 返回所有user对象的id的和
3》 in_groups_of(arg1, arg2) 将某一个数组分为子元素由arg1个元素组合的数组元素组成的数组,出现无法填充的值由arg2填补。
eg:
[1,2,3,4,5].in_groups_of(2,"blank") =>
[[1,2],[3,4],[5,"blank"]]
字符串扩展
str[0] 第一个字符的Ascill码。
str[2..3] 返回字符串的第三个字符开始的3个字符组成的字符串。
str.at(0) 第一个字符
str.to(4) 前5个字符组成的字符串
str.from(4) 最后5个字符组成的字符串
str.first
str.last
str.starts_with?(字符串)
str.ends_with?(字符串)
str.each_char{|char| char.upcase}
str.pluralize 复数形式
str.singularize 单数形式
str.humanize
str.titleize
对数值的扩展:
figure.ordinalize 返回数字的序数形式
figure.bytes、kilobytes、megabytes、gigabytes、terabytes、
perabytes、exabyte 数据大小
figure.seconds、minutes、hours、days、weeks、fortnights、months、years 时间
注意: ago、 until、 from_now、 since
eg:
1.day.ago
1.day.ago(Time.now)
时间和日期的扩展
now = Time.now
now.to_s(:short)、to_s(:db)、to_s(:long)、to_s(:rfc822)
now.ago(2.days)、since(2.days)
change(:hour => 12) 改变日期的hour为12
advance(:hour => 12) 推迟日期的12hour
to_date、to_time
at_beginning_of_week、at_beginning_of_month、at_beginning_of_quarter(季)、at_beginning_of_year
ruby符号的扩展:
posts.group_by{|post| post.author_id}
posts.group_by(&:author_id)
with_options的使用:
Rails里有些方法使用一个Hash作为最后一个可选的参数,如果对多个方法有同样的选项,我们可以使用with_options来减少冗余:
eg:
with_options :if => :should_validate_password? do |user|
user.validates_presence_of :password
user.validates_confirmation_for :password
user.validates_format_of :password, :with => /^[^\s]+$/
end
迁移任务:
create_table
:force => true 如果表存在,强制删除,然后再创建表
:temporary => true 创建一张临时表,程序与数据库断开链接,则表被删除。
:options => "xxxx" 指定针对于底层数据库的选项,这些选项会被加到create table语句的后面
:primary_key 主键
:id => false 没有主键的表
如果迁移任务 提供的方法 不够满足你 的需要,也 可以使用数 据库专有的 功能:使用execute() 方法就可以运行原生 SQL 语句。例如:给表加上外键
class CreateLineItems < ActiveRecord::Migration
def self.up
create_table :line_items do |t|
t.column :product_id, :integer
t.columnrder_id, :integer
end
execute "alter table line_items
add constraint fk_line_item_products
foreign key (product_id) references products(id)"
end
def self.down
drop_table :line_items
end
end
ActiveRecord::Base
column_names 属性组成的数组
columns_hash["属性名称"] 属性名称信息
属性_before_type_cast 读取属性时,ActiveRecod会尽量将得到的值转型成适当的ruby类型,如果我们希望的到属性的原始值,可以在属性名称后面加上before_type_cast。
eg:User.first.created_at => 2010-06-24 09:41:17
连接数据库: ActiveRecord::Base.establish_connection(:adapter => "mysql", :host => "localhost", :database => "rails", :username => "root", :password => "1234")
防止恶意注入:
1> 问号占位符: User.find(:all, :conditions => ["id > ?", 3]
2> 命名占位符: User.find(:all, :conditions => ["id > :id", {:id => 3}])
注意:
命名占位符的语句可以转换为
User.find(:all, :conditions => ["id > :id", params[:user]])
获取字段统计信息:
average:
maximum:
minimum:
sum :
count :
以上方法的参数:
:conditions、:joins、:limit、:order、:having、:select、 :distinct
eg:
Order.maximum :amount, :group => "state", :limit => 3,rder => "max(amount) desc"
拥有订单最大的三个州
更新操作:
update_attribute、update_attributes、update、update_all
创建操作:
create、create!、save、save!
删除数据:
delete、delete_all、destroy、destroy_all
delete绕过了ActiveRecord的回调和验证,destory没有绕过回调和验证
序列化数据:
serialize :属性
序列化的属性可以直接存入Array和hash类型的数据,也可以直接读出来使用
缺点:
ruby应用之外的应用访问序列化的数据时,除非它能够理解yaml格式,否则无法获取这个字段的信息。
弥补这种缺点的方式是用对象聚合的方式来实现类似的效果
聚合/组合:
聚合可以把一个或多个属性封装为一个类,然后这个类里可以添加操作属性的方法,这样我们就可以实现序列化所要实现的目的了,而且可以避免序列化的缺点。
composed_of :attr_name, :class_name => 类名称, :mapping => [字段与属性组成的数组]
eg:
class Xingxi < ActiveRecord::Base
composed_of :inf, :class_name => "Inf", :mapping => [[:name, :name], [:phone, :phone]]
end
class Inf
attr_reader :name, :phone
def initialize(name, phone)
@name = name
@phone = phone
end
def to_s
[@name, @phone].compact.join(" ")
end
end
inf = Inf.new("zcy", "12344454")
Xingxi.create(:inf => inf)
注意:
教程上指出 :class_name对应的“类名称”可以是类常量,也可以是包含类常量的字符串,但实际上只能是包含类常量的字符串,如果类名恰好是属性名的混合大写形式,那么class_name可以省略,但是实际上不可以,包括:mapping也不可以。
关联:
class Line < ActiveRecord::Base
belongs_to :product
end
belongs_to :product 会产生以下方法
1>:product(force_reload=false) 返回关联的product对象,默认情况下product对象会被缓存,当force_reload=true时,将重新查询数据库。
2>:product=: line对象和product对象关联起来,将line记录的外键值设为product的主键值,如果product没有保存,line保存的时候会保存product,包括外键。
3>:build_product(attributes={}) 新建一个product对象,用指定的属性对其初始化,相当于product=Product.new(attributes)。
4>:build_create(attributes={}) 创建一个product对象,与line关联,保存product对象。
order: has_one中也有order,主要用于例如最后一个***,此时便可以用order指定排序。
:dependent :destroy(true)、:nullify、 false
:destroy 删除记录的同时也删除子记录
:nullify 删除记录的同时删除子记录的外键
false 只删除记录
has_many :lines
class Product < ActiveRecord::Base
has_many :lines
end
has_many :lines 会产生以下方法
lines(force_reload=false) 同上
lines.build(attributes = {})
lines.create(attributes = {})
lines << line 将当前line对象添加到lines对象数组里
lines.push(line对象) line对象添加到lines
lines.delete(line,...) 删除一个或多个line对象,如果关联为:destroy => :destroy,子对象被删除,否则只是删除子对象的外键,打断与父对象的关联。
lines.delete_all 调用所有子对象的delete方法
lines.destroy_all 调用所有子对象的destroy方法
lines.clear 和delete一样,不同的是clear针对的是所有的子对象。
lines.find(options)
lines.count(options)
lines.size
lines.length 强制加载所有子对象,返回对象的集合。
lines.empty?
lines.replace(line对象数组) line对象数组替换原先的lines
lines.sum(options) 不便利内存中的子对象集合,直接在数据库端操作
lines.uniq 返回一个数组,包含所有具备独立id的子对象
1> finder_sql: 重新定义了统计子记录的sql语句
counter_sql: 重新定义了统计子记录的数目
注意: 如果指定了finder_sql而没有指定counter_sql,finder_sql中的子句会被替换为select count(*),然后记录子记录的数量。
eg:
has_manyingxis, :finder_sql => "select x.* from xingxis x, infos i where x.info_id = i.id and x.id > 4"
作用: 当:conditions无法满足时,:finder_sql显的非常重要。
:order : 以特定的顺序排列
:conditions : 返回符合条件的子记录
:dependent :destroy、:nullify、 false
:destroy 删除记录的同时也删除子记录
:nullify 删除记录的同时删除子记录的外键
false 只删除记录
多对多的关联有两种
1: 利用默认的关联表
2:自己创建关联表,利用关联中的:through
:through 告诉rails通过guanlians表来导航关联
:source 用来指定关联在那个属性上
:uniq => true 去掉重复的对象 等同于 :select => "distinct books.*"
eg:
class Kind < ActiveRecord::Base
has_many :guanlians
has_many :readers, :through => :guanlians, :source => :book
end
注意:
has_many :reader1s,:conditions => "guanlians.cishu > 0"
当使用conditions不能很好的表达时,无法提供参数,可以考虑以下格式,而且当同样的方法被多次调用时,可以将方法写在模块中,然后在关联中:extend => "模块名称" 来调用。
has_many :readers do
def reader(limit = 3)
find(:all, :limit => limit)
end
end
单表继承:
优点: 这样做的好处是提高读取表的速度,因为没有关联,只有一个表。
缺点: 当各个子类的相似的地方很少的时候,会导致表中有很多属性,这样处理这个问题的方法是用多态关联。
多态关联:
types表中的多态外键如果是duotai,那么表的属性是duotai_id, duotai_type,一个记录键值,一个记录类名。
class Article < ActiveRecord::Base
has_one :type, :as => :duotai
end
class Image < ActiveRecord::Base
has_one :type, :as => :duotai
end
class Type < ActiveRecord::Base
belongs_to :duotai, :polymorphic => true
end
自引用的连接:
class Employee < ActiveRecord::Base
belongs_to :boss, :class_name => "Employee", :foreign_key => :employee_id
end
预先读取子记录
以下实例如果没有:include => :people, infos为n, 那么他将执行2n+1次,如果指定了:include,将预加载与info有关的people记录,此时将提高效率,但是如果预加载了数据,但没有用这些数据,反而会降低效率。
Benchmark.bm() do |x|
x.report{
infos = Info.find(:all, :include => :people)
infos.each do |info|
info.people.name
end
}
end
如果一个对象刚刚创建出来,还没有与数据库记录建立映射,我们称它为新对象(new records)。调用new_records?
模型验证:
validate、 validate_on_create、 validate_on_update
ActiveRecord::Errors
[] info.errors[:email]
on info.errors.on(:email)
add(:属性, 信息)
size、length、count
each、each_error 迭代错误属性和错误属性对应的信息
each_full 迭代错误信息
full_messages 错误信息组成的数组
invalid?(属性) 如果属性无效,则返回true
to_xml
empty?
ActiveRecord::Errors.default_error_messages 这个返回所有的默认信息,如果修改默认信息的话,可以从这里修改。
回调:
创建方式
1:直接在回调中写代码。
2:声明回调处理器,处理器可以是一个代码块也可以是一个方法,如果用方法作为一个处理器,应该被声明为private或protected。
eg
def before_save
...
end
before_save :check
private
def check
end
注意:以下方法将跳过回调
* decrement
* decrement_counter
* delete
* delete_all
* find_by_sql
* increment
* increment_counter
* toggle
* update_all
* update_counters
ActiveRecord::Base
column_names: 所有列名组成的数组
columns: 所有包含列信息的对象组成的数组。
columns_hash: 列名与列对象组成的hash数组。
实例方法:
attributes: 所有属性和属性值组成的hash数组。
attributes=
attribute_names: 所有属性组成的数组。
attribute_present?(属性名称) 如果属性名称存在,则返回true,反之亦然。
事务: 要么全部执行,要么全部不执行。
模型类.transaction do
end
begin ... rescue ...end
eg:
class Info < ActiveRecord::Base
def validate
errors.add(:age, "age is not less than 0") if age < 0
end
def jian(i)
self.money = self.money - i
self.save!
end
end
info = Info.create!(:money => 100)
begin
Info.transaction do; info.jian(200); end
rescue
end
puts info.money =》 -100
该实例中要求money不能小于0,而我们也做到了,表中的数据不会被改,但是info.money 返回的值是-100,模型对象的值被该变了,这是因为ActiveRecord没有跟综对象在事务前后的状态,我们可以指定事务跟踪哪些模型对象。
Info.transaction(info) do; .... end,此时输出的值就是100了。
路由:
map.connect 重要参数
:requirements => {:name => /regexp/} 要求url中特定的组成部分与指定的正则表达式一一匹配。
:defaults => {:name => "value", ...} 设定各组成部分的默认值
:conditions => {:name => /regexp/orstring,...} 设定路由的条件
:name => value 设定:name参数的默认值
eg:
map.connect 'infos/:year', :controller => "infos", :action => "hello", :defaults => {:year => 2008},:requirements => {:year => /(19|20)\d\d/}, :conditions => {:method => :get}
注意:
map.connect "*aa", :controller => "", :action => ""
符合任何的url格式,但是一定要注意的是要放在最后,否则其他的路由都无法匹配了。
有名路由
map.hello "hello/:id", :controller => "infos", :action => "index"
1> hello_url(:id => 1)或hello_url :controller => "infos", :action => "index"
可以访问这个url。
注意: 以上url可以用path替代。
2> 地址栏中可以输入hello访问这个url。
资源路由:
map.resources :articles, :collection => {:recent => :get}, :member => {:release => :put}, :new => {:hello => :get}
增加以下规则:
recent_articles_path
release_article_path(:id => 1)
hello_new_article_path
map.resources :articles do |article|
article.resources :comments
end
articles/99/comments/4
控制器环境(可以在action中直接引用)
controller_name: controller名称
action_name: action名称
session: session
cookies: cookie
params: 存放着参数的hash对象
rsponse
request: 进入控制器的请求对象,包含属性。
domain: 请求地址域名部分的最后两端。
remote_ip: 客户端的ip地址。
env: 返回请求的环境。
get?、post?、put?、delete?、head?
method: 返回客户端访问所使用的请求方法。
xhr?或xml_http_request? 如果请求来自AJAX的辅助方法,则返回true,否则返回false。
控制器应答:
1:渲染一个模板,最常见的(.html、 .rxml、 .rjs)。
2:返回一个字符串给浏览器,主要用于发送错误提示。
3:发送html以外的数据,这种方式通常用于提供下载。
控制器每次只响应一个请求:
render、 redirect_to、 send_xxx
1> render :action
2> render :template
3> render :file
4> render :partial 调用局部模板
:object 指定传递给局部模板的对象。
5> renderml
6> render :nothing
7> render :inline
8> render :text
9> render(:update) do |page| ... end
重要参数:
:locals => {},指定模板要使用的局部变量。
:layout => false|nil|true|模板名称。
render_to_string 可以当作render使用,不过它不会跳转,只会把整个的内容作为字符串返回。
method_missing:调用指定的action名称无效时,method_missing会渲染一个内联的模板,将action的名称和请求参数显示出来。
eg:
def method_missing(name, *args)
render(:inline => %{<h2> Unknown action: #{name}</h2>
Here are the request parameters:<br/>
<%= debug(params) %>})
end
send_data(data, options) 发送一个数据流给客户端。
参数:
:filename、 disposition(inline|attachment)、status、type
send_file(path, options) 发送一个文件给客户端
参数:
:filename、 :disposition、 :status、 :type、 buffer_size、 stream
重定向:
redirect_to(:action => "")
redirect_to(path)
redirect_to(:back) 返回上一页,注意:如果redirect_to(:back)写在了index的action中,并且访问index的时候能够直接运行redirect_to(:back),则不能直接访问index的action,因为他会跳转上一页,但是没有上一页。
过滤器:
prepend_before_filter
before_filter、append_before_filter
prepend_after_filter
after_filter、append_before_filter
参数:
:only、 :except
定义过滤器的方式:
1:
before_filter do
...
end
2:
before_filter :hello,nly => [:show, :index]
skip_filter、 skip_before_filter、skip_after_filter
参数:
:only、 :except
缓存:
片段缓存、 页面缓存、 action缓存
caches_page、 caches_action、 cache do .... end
默认配置下,cache只有在产品环境下才生效,如果要在开发环境下生效,要配置以下信息中的一条。(config/environments/development.rb)
ActionController::Base.perform_caching = true|false
config.action_controller.perform_caching = true
解除缓存:
expire_action、 expire_page、 expire_fragment :controller => "...", :action => "..."
1》默认:缓存片段的名字取决于渲染该页面的控制器名称和action名称,所以使用expire_fragment指定控制器名称和action名称来是对应的片段缓存失效。
2》指定缓存名称(等同于url_for的参数)
缓存存储机制的全局设置(environment.rb设置):
缓存目录:
config.action_controller.page_cache_directory = RAILS_ROOT + "/public/caches"
缓存类型:
config.action_controller.page_cache_extension = ".html"
缺点:导致大量的数据从网络驱动器传输到某一台具体的web服务器,然后将这些数据发送给用户,所以,如果在高吐量的网站中使用这种存储机制,服务器之间的网络宽带应该非常宽。
缓存存储体系只对action缓存和片段有效,全页面缓存必须以文件的形式放在public目录下。
页面缓存是最快速的一种缓存应用。那么应该在什么时候使用他呢?
1、对于所有用户都相同的页面
2、公开的页面,没有用户认证的页面
缓存分页:
因为页面缓存的时候会忽略掉像/blog /list?page=2这样的参数,所以你需要使用/blog/list/2这样的地址形式,而原来我们使用的是id保存参数值,现在我们需要用 page来保存参数值。
下面我们修改 /config/routes.rb文件
map.connect 'blog/list/:page',
:controller => 'blog',
:action => 'list',
:requirements => { :page => /\d+/},
:page => nil
使用了新的routes定义,我们的连接也应该改成
<%= link_to "Next Page", :controller => 'blog', :action => 'list', :page => 2 %>
最终的连接结果是"/blog/list/2",当我们点这个连接的时候,后台会处理两件事情
1、应用将2放入page这个参数中,而不是原来id这个参数
2、缓存将生成 /public/blog/list/2.html 这个页面
所以,缓存分页,就要将页面参数变成页面的一部分,而不要使用地址参数的形式,他是会被忽略的。
解决危险链接的方式:
1:使用表单和按钮(button_to)
2:使用确认页面
link_to、link_to_if、link_to_unless、button_to
stylesheet_link_tag
javascript_include_tag: 假设文件在public/javascripts目录
对象调用属性:
eg: info.name 或 info["name"]
form_for、 form_tag
form_for(:info, @info, :url => {:action => "create"}, :html => {:method => "post"}
:info 告诉rails正在操作哪个模型类的对象
@info 通过哪个实例变量获得该对象
:url 访问的action地址
:html 定义访问的方法,可以定义:multipart => true,上传。
select标签:
1>collection_select(:post, :author_id, Author.all, :id, :name_with_initial, {:prompt => true})
2>select、select_tag "people", "<option>David</option>"
3>options_from_collection_for_select(@people, 'id', 'name')
4>options_for_select({ "Basic" => "$20", "Plus" => "$40" }, "$40")
子表单:
<% fields_for :name, @info.name do |field| %>
Name: <%= field.text_field :name %>
<% end %>
卸载layout页面中:
<% content_for :head do %>
<ul><li>a</li><li>b</li></ul>
<% end %>
<%= yield :head %>
发送邮件:
config.action_mailer.delivery_method = :smtp|:sendmail|:test
开发环境下默认的设置是:smtp。
:smtp、:sendmail 可以让ActionMailer发送邮件。
:test 可以用于单元测试和功能测试,电子邮件不会发送出去,而是被放入一个数组。
禁止开发环境下发送邮件:
config/environments/development.rb中设置config.action_mailer.delivery_method = :test
config.action_mailer.perform_deliveries = true|false
perform_deliveries为true,邮件被正常发送,否则不发送,用于测试。
config.action_mailer.raise_delivery_errors = true|false
设置邮件发送过程中的异常是否抛还给应用程序。false为忽略,true为抛还。
config.action_mailer.default_charset = "utf-8"
设置发送邮件的字符集。
ActionMailer::Base.smtp_settings = {
:address => "smtp.163.com",:port => 25,:domain => ".com", :authentication => :login,:user_name => "zhangcaiyan0123@163.com",:password => "zhangcaiyan",}
设置smtp服务器(其中domain是域名称)
ruby script/generate mailer OrderMailer confirm sent
模型中定义方法:
def confirm(sent_at = Time.now)
subject '标题'
recipients "zhangcaiyanbeyond@gmail.com"
from 'zhangcaiyan0123@163.com'
sent_on sent_at
body "邮件正文"
end
bcc 暗送
cc 抄送
charset 默认为smtp_settings中的default_charset属性
subject 标题
from 发件人的邮箱
recipients 收件人的邮箱
body 正文
send_on 发送时间
headers 指定邮件的头信息
attachment(上传插件) :filename => 文件名称, :body => 文件内容(file.read), :content_type => "内容类型"
OrderMailer.deliver_confirm 发送邮件
email = OrderMailer.create_confirm 创建邮件对象(TMail::Mail对象)
OrderMailer.deliver(email)
注意: OrderMailer是模型类,create_confirm中的create是表示要创建对象,confirm是表示模型类中的方法,deliver表示要发送邮件。
保护rails应用:
防御sql注入攻击:
eg:这个实例就是恶意注入的例子,其中1为true,他会查处表中的所有数据。
Core::User.find(:all, :conditions => "id > '' or 1")
防止恶意注入:
绝对不要用ruby的#{...}机制直接把字符串插入到sql语句中,而应该用Rails提供的变量绑定。
eg:
Core::User.find(:all, :conditions => ["id > ?", 3])
Core::User.find(:all, :conditions => ["id > :id", {:id => 3}])
用参数直接创建记录:
User.create(params[:user])
为了防止用户模拟一些属性提交,我们可以将某些属性保护起来。
attr_protected :属性1, :属性2 列出被保护的属性
attr_accessible :属性1, :属性2 列出允许自动赋值的属性,也就是说除此之外的都是被保护的属性
被保护的属性也就是不能通过create(params[:user])直接保存,而是需要通过赋值才可以。eg:
user = User.new
user.role = params[:role]
user.save
不要相信ID参数:
当我们通过id查找出数据,然后对数据进行操作时,我们要注意某些情况:例如当我们浏览(/show/id)某个用户的数据时,可以利用url浏览其他用户的数据,为了防止这样的事发生,可以这样:
eg:
1》 order = Order.find(params[:id], :conditions => ["user_id = ?", user_id])
2》 order = @user.orders.find(id)
3》 order = @user.orders.find(id).destroy
防御XSS攻击:
攻击者把自己编写的javascript脚本放进网页,来获得他们想要的cookie,我们可以通过rails提供的h(string)辅助方法(实际上是html_escape()方法的别名)
生成rails项目的HTML文档
rake doc:app
ActiveRecord::Errors.default_error_messages = hash
修改默认错误显示信息
named_scope的使用:
named_scope :quanbu, :conditions => ["name=zcy"]
named_scopeianzhi, :lambda{|limit|{:limit = limit}}
Shili.quanbu.xianzhi(3)
显示错误页面: 当指定的异常发生时,将显示特定的页面,这个最好放到application_controller中
rescue_from 异常, :with => :action
eg:
rescue_from Exception, :with => :error
def error
render :file => "novel/infos/error", :layout => "novel"
end
对于boolean类型的数据,应该省略前面的is_,ActiveRecord会自动加个?号,映射成actived? ,不是boolean型的数据也会也会扩展?
_form下的共享表单,区间的情况
1:map.namespace :doctor do |doctor|
doctor.resources :patients
end
["doctor", @patient ]
2:map.resources :doctor do |doctor|
doctor.resources :patients
end
[@doctor, @patient ]
发表评论
-
rails console 记录命令历史
2020-03-20 10:53 3501: 打开文件: vim ~/.irbrc,添加如下内容: ... -
mysql dyld: Library not loaded: /usr/local/opt/openssl/lib/libssl.1.0.0.dylib
2019-12-16 16:43 435今天一连串的神操作导致连接mysql一直报错,dyld: Li ... -
ruby gsub和sub 的特殊使用
2019-04-04 19:53 1042gsub和sub使用 常用的使 ... -
rails离线环境搭建相关命令
2018-12-17 09:35 4501:下载yum包: 环境搭建需要安装很多包,可以使用 yumd ... -
rails离线环境搭建相关命令
2018-12-17 09:35 4771:下载yum包: 环境搭建需要安装很多包,可以使用 yumd ... -
rails5 belongs_to 默认不能为空,报错must exist
2017-04-29 16:37 4831: 在config/application.rb设置 con ... -
随笔知识
2014-08-07 21:11 1836show-source: 查看方法在文件中的位置,show-s ... -
rails 中 group 按照一定的规则返回数据
2012-11-03 19:20 970has_many :user_resumes, class_n ... -
项目 经验
2012-10-10 15:53 01: user = User.first; user. ... -
数组使用will_paginate
2012-03-30 11:58 1437有的时候,在开发的过程中需要对模型数组进行分页,此时我们可以如 ... -
我的rails 编程规范
2012-01-16 15:19 8961: 属性中时间要已at结尾,例如created_at, ... -
html_safe
2012-01-12 13:56 1432html_safe: 可以保证(> < &am ... -
同时分页查找没有关联关系的多个表
2011-12-30 14:41 1291supplyinfos和seekinginfos两个表 需求: ... -
send_file ie下文件名乱码问题解决
2011-10-28 17:50 2475使用rails的send_file 实现下载功能时,type指 ... -
counter_cache的使用
2011-10-08 11:55 2732有点惭愧,做rails也2年了,竟然不会用co ... -
has_many 关联关系表单 提交
2011-04-18 17:16 1155class Author has_many :books ... -
belongs_to 多级关联关系
2011-04-12 14:18 1129有一种情况,是这样的c属于b,b属于a,但是我们有时候想建立c ... -
rails 根据异常显示特定的错误页面
2011-03-27 20:50 1177rescue_from 异常, :with => :a ... -
rails 发送电子邮件(ActionMailer)
2011-03-27 20:49 36361: 复制以下配置邮件 ... -
rails 读写分离
2011-03-27 20:48 2031开发环境下实现rails的 ...
相关推荐
基于springboot教育资源共享平台源码数据库文档.zip
linux开发篇,配套视频:https://www.bilibili.com/list/474327672?sid=4493702&spm_id_from=333.999.0.0&desc=1
ReadEra 这个阅读应用能够打开下列任何格式的文档: EPUB, PDF, DOC, RTF, TXT, DJVU, FB2, MOBI, 和 CHM. 基本上来说,你可以用它阅读你的设备内存中的任何书籍或者文本文档。 这个应用与划分成章节的文档兼。,有一个书签功能,可以在你阅读的时候,自动保存你的进度。另外,它让你更改页面模式,从几种不同的主题中进行挑选(夜间,白天,棕黑色调,还有控制台)。
软件环境:KEIL4 硬件环境:STM32单片机+舵机 控制原理:通过控制输出信号的占空比调节舵机旋转的角度
基于springboot仓库管理系统源码数据库文档.zip
酒店管理系统源码C++实现的毕业设计项目源码.zip,个人大四的毕业设计、经导师指导并认可通过的高分设计项目,评审分98.5分。主要针对计算机相关专业的正在做毕设的学生和需要项目实战练习的学习者,也可作为课程设计、期末大作业。 酒店管理系统源码C++实现的毕业设计项目源码.zip,酒店管理系统源码C++实现的毕业设计项目源码.zip个人大四的毕业设计、经导师指导并认可通过的高分设计项目,评审分98.5分。主要针对计算机相关专业的正在做毕设的学生和需要项目实战练习的学习者,也可作为课程设计、期末大作业。酒店管理系统源码C++实现的毕业设计项目源码.zip酒店管理系统源码C++实现的毕业设计项目源码.zip酒店管理系统源码C++实现的毕业设计项目源码.zip,个人大四的毕业设计、经导师指导并认可通过的高分设计项目,评审分98.5分。主要针对计算机相关专业的正在做毕设的学生和需要项目实战练习的学习者,也可作为课程设计、期末大作业。酒店管理系统源码C++实现的毕业设计项目源码.zip,个人大四的毕业设计、经导师指导并认可通过的高分设计项目,评审分98.5分。主要针对计算机相关专业的正在做毕
58商铺全新UI试客试用平台网站源码
springboot vue3前后端分离 基于SpringBoot+Vue的轻量级定时任务管理系统.zip
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过严格测试运行成功才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。
4D毫米波雷达点云数据处理方法研究.caj
S M 2 2 5 8 X T 量产工具供大家下载使用
基于springboot的文物管理系统源码数据库文档.zip
基于springboot的电影院售票管理系统源码数据库文档.zip
基于Java web 实现的仓库管理系统源码,适用于初学者了解Java web的开发过程以及仓库管理系统的实现。
美容美发项目,使用django框架,前后端一体化项目
在线票务:2023年中国在线票务行业市场规模约为24.99亿元,挖掘市场蓝海新机遇 在数字浪潮的席卷下,传统的票务销售模式正经历着前所未有的变革。纸质门票逐渐淡出人们的视野,取而代之的是便捷、高效的数字和移动票务。这一转变不仅为消费者带来了前所未有的购票体验,更为在线票务平台开辟了广阔的发展空间和市场机遇。随着国民经济的持续增长和文体娱乐行业的蓬勃发展,中国在线票务行业正站在时代的风口浪尖,等待着每一位有志之士的加入。那么,这片蓝海市场究竟蕴藏着怎样的潜力?又该如何把握机遇,实现突破?让我们一同探索。 市场概况: 近年来,中国在线票务行业市场规模持续扩大,展现出强劲的增长势头。据QYResearch数据显示,2023年中国在线票务行业市场规模约为24.99亿元,尽管受到宏观经济的影响,市场规模增速放缓,但整体趋势依然向好。这一增长主要得益于国民人均收入的不断提高、电影及演出行业的快速发展以及政府政策的支持。例如,2023年财政部、国家电影局发布的《关于阶段性免征国家电影事业发展专项资金政策的公告》,为电影行业注入了强劲动力,进而推动了在线票务市场规模的扩大。 技术创新与趋势: 技术进步
基于SpringBoot的养老院管理系统源码数据库文档.zip
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过严格测试运行成功才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。
内容概要:本文档是一份详细的Go语言教程,从基础概念介绍到高级主题均有覆盖。主要内容包括Go语言的基础语法、数据类型、控制结构、函数、结构体、接口和并发编程等方面。通过具体示例介绍了如何使用Go语言进行开发。 适合人群:初学者和有一定经验的程序员都可以从这篇教程中受益,特别是那些想要快速掌握Go语言并应用于实际项目的开发者。 使用场景及目标:适用于初学者系统学习Go语言的基础知识和常用功能;也可以作为已有开发经验者的参考资料,帮助他们解决具体的编程问题,提高开发效率。 其他说明:本教程不仅包含了Go语言的基本知识点,还重点讲解了其独特的并发编程模型。读者在学习过程中应该注重理论与实践相结合,通过实际编写代码来加深理解和记忆。
基于springboot计算机基础网上考试系统源码数据库文档.zip