美文网首页程序员
ruby语言断断续续的编程笔记分享

ruby语言断断续续的编程笔记分享

作者: 程序员小哥哥 | 来源:发表于2018-07-23 18:15 被阅读12次
    ruby语言断断续续的编程笔记分享

    断断续续继续了一些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

    官网:https://activeadmin.info/

    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基础汇总

    相关文章

      网友评论

        本文标题:ruby语言断断续续的编程笔记分享

        本文链接:https://www.haomeiwen.com/subject/ijgjmftx.html