断断续续继续了一些ruby编程的笔记,都是一些很继续的东西,在简书这里汇总一下。
一:如何使用Pundit进行权限管理
1.1:pundit介绍
有名的权限管理gem:
1.pundit:流行的权限管理(推荐,pundit更加适合大型项目,更加复杂的权限系统)
2.authority: 已经不维护了
3.cancancan: 比较老牌的权限管理的gem
作用:针对不同的用户执行不同的操作(不同的用户有不同的角色管理)
注意:用户级别的角色管理,pundit是不包含这个功能的,角色的管理需要我们自己来设计和实现
pundit这个gem是需要根据我们自己所需要的逻辑,比如哪样的用户能够干什么事情,说白了就是哪些用户
能够执行这个action,哪些用户可以执行特定的逻辑操作,总得来说,pundit主要是做后端的一个权限管理的一个gem.
1.2:Pundit安装和配置
1.在Gemfile中引入:
gem 'pundit'
bundle install
3.在app/controller/application_controller.rb中引入pundit这个模块
include Pundit
说明:引入pundit这个模块之后,我们就可以在controller和view中使用对应的方法来判断对应的权限了
4.运行pundit初始化命令
rails g pundit:install
说明:运行完这条命令之后会生成app/policies/application_policy.rb这个文件
5.在config/application.rb加入下面的语句,让其能自动加载
config.autoload_paths += %W[#{config.root}/app/policies]
1.3:Pundit的使用
这里首先要明确几点:
- pundit策略的设置都是纯根据ruby的类来实现的
- 一个方法,比如index?是否返回true和false,是我们能够使用app/policies/application_policy.rb这个文件里user、record两个变量来判断当前的action是否返回true和false
- policy设计的思路,每一个policy文件都是和模型对应的。比如传过来的是一个post这个record,pundit就会查找app/policies/下是否有PostPolicy这个类,然后调用这个类的同名的这个方法,进而判断权限,pundit和rails相似,有预先的约定和猜测。
举个例子:
只有这个用户发表的文章,他才有删改的权限
1)运行命令
rails g controller posts index show
在posts这个表创建个title这个列就行
2)在app/model/user.rb
下
class User < ApplicationRecord
has_many :user
end
app/model/post.rb
class Post < ApplicationRecord
belongs_to :user
end
3)在rails c中创建下测试数据
user = User.first
user.posts.create title: "Post 1"
user.posts.create title: "Post 2"
user2 = User.last
user.posts.create title: "Post 3"
user.posts.create title: "Post 4"
4)在app/controllers/posts_controller.rb中增加简单的逻辑
class PostsController < ApplicationController
def index
@posts = Post.includes(:user)
end
def show
@post = Post.find params[:id]
end
def edit
@post = Post.find params[:id]
authorize @post #authorize是include Pundit提供的
end
end
5)在config/routes.rb增加对应的路由
resources :posts
6)view层
app/views/posts/index.html.erb
<h1>Posts</h1>
<ul class="list-group">
<% @posts.each do |post| %>
<li class="list-group-item">
<%= link_to post.title, post_path(post) %>,
ID: <%= post.id %>,
作者: <%= post.user.email %>
<% if policy(post).edit? %>
<%= link_to "编辑", edit_post_path(post), class: "btn btn-primary" %>
<% end %>
</li>
<% end %>
</ul>
app/views/posts/show.html.erb
<h1>Posts</h1>
<h2><%= @post.title %></h2>
<p>作者: <%= @post.user.email %></p>
app/views/posts/edit.html.erb
<h1>Posts</h1>
<h2>编辑:<%= @post.title %></h2>
7)app/policies/policy.rb
class PostPolicy < ApplicationPolicy
def edit?
user.has_role?('admin') || user == record.user
end
def can_edit?
true
end
end
说明:会识别PostPolicy这个类,ApplicationPolicy有个user属性,指的是current_user,ApplicationPolicy在实例化的时候,会初始化这个属性
二:log4R配置
1.在config目录下,创建一个log4r的配置文件: config/log4r.yml,内容编辑如下
log4r_config:
# define all loggers ...
loggers:
- name : production
level : WARN
trace : 'false'
outputters :
- datefile
- name : development
level : DEBUG
trace : 'true'
outputters :
- datefile
# define all outputters (incl. formatters)
outputters:
- type: DateFileOutputter
name: datefile
dirname: "log"
filename: "my_app.log" # notice the file extension is needed!
formatter:
date_pattern: '%H:%M:%S'
pattern : '%d %l: %m '
type : PatternFormatter
2.修改config/application.rb文件如下
require 'rails/all'
# add these line for log4r
require 'log4r'
require 'log4r/yamlconfigurator'
require 'log4r/outputter/datefileoutputter'
include Log4r
Bundler.require(:default, Rails.env) if defined?(Bundler)
module Zurich
class Application < Rails::Application
#...
# assign log4r's logger as rails' logger.
log4r_config= YAML.load_file(File.join(File.dirname(__FILE__),"log4r.yml"))
YamlConfigurator.decode_yaml( log4r_config['log4r_config'] )
config.logger = Log4r::Logger[Rails.env]
end
end
3.修改gemfile文件,增加log4r这个gem
gem 'log4r', '1.1.9'
这时候重启rails,就会发现log目录,会根据日期创建相应的log目录了。
三:后台框架-activeadmin
activeadmin code:https://github.com/activeadmin/activeadmin
gemfile:
gem 'activeadmin'
# Plus integrations with:
gem 'devise'
gem 'cancan' # or cancancan
gem 'draper'
gem 'pundit'
bundle install
3.1 set-up activeadmin
如果你不想使用devise
rails g active_admin:install --skip-users
如果想用已经存在的User
rails g active_admin:install User
other
rails g active_admin:install
会生成这些文件
app/admin/dashboard.rb
app/assets/javascripts/active_admin.js
app/assets/stylesheets/active_admin.scss
config/initializers/active_admin.rb
然后依次执行一下命令
rake db:migrate
rake db:seed
rails server
这些在官网安装指南介绍的都很详细,这里列出我在实际项目中会用到的一些功能。
这里也可以尝试一下实际效果
3.2 自定义action
ActiveAdmin.register User do
index do
actions do |u|
link_to('获取用户下级所有姓名', "/admin/users/#{u.id}/get_names", method: 'get')
end
end
end
member_action :get_names, :method => :get do
#处理业务逻辑,这里get请求,接收params[:id]参数
render json: your_json_info
end
3.3 scope、filter、selectable_column、
1.scope:列表上面进行对列表中数据进行筛选,在model有需要有专门的方法存在。
2.filter:filter默认会过滤所有model的数据,这里如果指定,将会覆盖原本默认存在的。
3.4 index
1.selectable_column:在列表左方增加可以选择的按钮,这里一般是为了可以进行批量删除/处理操作。
2.id_column:显示字段的id字段。
3.如果不定义index是默认显示全部。跟filter一个道理,这里定义column
可以根据实际需要显示需要展示的列。
3.5 form
1.用input来定义需要添加/修改的列
如果需要将某几个字段放在一起,然后用指定的名字定义下面的字段,可以这样写:
form do |_|
inputs '这里展示区域_a' do
column: a_1
column: a_2
end
end
另外input中针对于特殊字段,可以显示出特定的格式:
1.1 日期:
input :push_start_time, as: :datepicker, label: '开始时间' #这里显示的是yyyy-mm-dd
input :push_start_time, as: :date_picker, label: '开始时间' #这里显示的是yyyy-mm-dd mm:dd::ss
1.2 下拉:
input :order_info, as: :select, collection: [['有订单', true], ['无订单', false]], label: '适用人群', selected: '有订单' #下拉按钮,这里可以设置选中哪一个
1.3 上传:
input cover as: file, label: "封面", hint: "233x292"
1.4 单选:
input :plans, as: :check_boxes,
label: '人员限制',
collection: [:user_a, :user_b],
selected: :user_a #注意,这是是symbol
这里有一个值得注意的点,我发现每次保存的时候,都无法将plans保存到数据库中,我在permit_params也写入了plans,对了在admin/你的model.rb中需要写入permit_params,这里是允许哪些字段,这就是rails的健壮参数了,这里不多做概述,回归整体,这里针对于plans不能写
permit_params :plans
因为plans是check_boxes,这里需要指定格式
permit_params plans: []
这样就好了
3.6 other
1.还有一种情况,你可能在设计表的时候,可能采用一个列中存在多个字段的情况,这就需要在model进行序列化的操作,那在activeadmin中如果展示出来呢
看下面的两个文档,或许能解决你的问题:
JSON Serialized Columns with Rails
Dealing with JSON data in Active Admin
2.针对于notice flash消息不能正常显示的问题
Add flash messages for actions
四:rails中的reject和merge方法
在进行rails开发的时候,针对于hash最常用的方法是reject和hash的方法
4.1 reject方法
1)reject方法和描述
hash.reject { |key, value| block }
类似 delete_if, 但作用在一个拷贝的哈希上。相等于 hsh.dup.delete_if。
2)reject!方法和描述
hash.reject! { |key, value| block }
相等于 delete_if, 但是如果没有修改,返回 nil。
2.3.3 :001 > h = {:a => 1, :b => 2}
=> {:a=>1, :b=>2}
2.3.3 :002 > h.delete(:a)
=> 1
2.3.3 :003 > h
=> {:b=>2}
2.3.3 :004 > h = {:a => 1, :b => 2}
=> {:a=>1, :b=>2}
2.3.3 :005 > h.delete_if {|k,v| v != 3}
=> {}
2.3.3 :006 > h
=> {}
2.3.3 :007 > h = {:a => 1, :b => 2}
=> {:a=>1, :b=>2}
2.3.3 :008 > h.reject{|k, v| v!=2}
=> {:b=>2}
2.3.3 :009 > h
=> {:a=>1, :b=>2}
2.3.3 :010 > h = {:a => 1, :b => 2}
=> {:a=>1, :b=>2}
2.3.3 :011 > h.reject!{|k, v| v!=2}
=> {:b=>2}
2.3.3 :012 > h
=> {:b=>2}
2.3.3 :015 > h = {:a => 1, :b => 2}
=> {:a=>1, :b=>2}
2.3.3 :016 > h.reject{|k, v| v!=2}
=> {:b=>2}
2.3.3 :017 > h
=> {:a=>1, :b=>2}
2.3.3 :018 > h.reject!{|k, v| v!=2}
=> {:b=>2}
2.3.3 :019 > h
=> {:b=>2}
2.3.3 :020 > h.reject!{|k, v| v!=2}
=> nil
4.2 merge方法
1)merge方法和描述
hash.merge(other_hash) [or]
hash.merge(other_hash) { |key, oldval, newval| block }
2)merge!方法和描述
hash.merge!(other_hash) [or]
hash.merge!(other_hash) { |key, oldval, newval| block }
与 merge 相同,但实际上 hash 发生了变化。
other
更基础的东西,请看这篇ruby基础汇总
网友评论