3个 model,针对不同的 model 使用不同的 before_filter,最简单的做法。 如果复杂的情况简易用 cancan 另外,拒绝使用 if else,太丑了,
简单的权限的话,只需要加一个不用的 model 就可以了,比如只有 admin 和 user,在只有 admin 可以访问的时候增加 befor_filter 就可以了, 如果设计复杂的权限,那就 cancan 吧
建议你从设计 api 的角度来写 code。比如你要实现一个功能,你希望你的使用 api 是什么样子,先写出你的 api,然后再写测试,从测试的描述中让自己更清楚自己要做什么,测试出错的结果是你想要的结果时,再动手写 code。 比如我想实现所有的 model 按照时间来分组的功能,那么我希望的是:
User.aggregate({created_at.lt: Time.now.....})
Order.aggregate(.....)
Product.aggregate(.....)
那么你就发现你其实希望的是所有的 model 做分组的结构应该是一样,这样你大致能想到自己要做什么了。
assets 启用时会自动加载 app 下 assets 目录里面的所有文件,你可以放在 app/assets/javascripts,也可以放在vendor/assets/javascripts,或者是你自己定义的目录,如果你只在一个页面会用到这个js的话,建议直接在erb中使用楼上说的javascript_include_tag,这样的话只在这一个页面会加载这个文件。但是要注意在发布production时需要将该文件加入到precompile。如果想简单一件,直接在application.js中require,在开发环境下因该可以直接看到该js了:)
如果你想写成 ruby style 的 code 的话,可以做一些 module,例如下面以前抽象出来的 module,直接集成在 model 上,api 就像这样
Model.aggregate_by_date(:field => FIELD, :from =>FROM, :to =>TO, :duration => year | month | day)
def aggregate_by_date *args, &block
options = args.extract_options!
duration = options[:duration]
self.aggregate do
match do |m|
if options[:field] && (options[:from] || options[:to])
m[options[:field]] = {}
m[options[:field]]["$gte"] = options[:from] if options[:from]
m[options[:field]]["$lt"] = options[:to] if options[:to]
end
end
group do |g|
g['count'] = {"$sum" => 1}
end
group_id do |id|
id.year = {"$year" => "$created_at"} if duration.include?("year")
id.month = {"$month" => "$created_at"} if duration.include?("month")
id.day = {"$dayOfMonth" => "$created_at"} if duration.include?("day")
end
yield(self)
sort do |s|
s._id = 1
end
end
end
建议参考 map_reduce 或者 mongodb 的 aggregate map_reduce 一般用来做一些复杂的数据模型,如果简单的话 aggregate framework 就可以解决。 你所说的两次访问 db 的性能暂时不考虑,以后可以用其他方法来解决,担心数据库性能不如担心 rails 性能。