zoukankan      html  css  js  c++  java
  • go Rails 知识点,Concepts Series:url和parameter; 建立Rails App Templates;报错页面debug; counter_cache

    Rails Concepts Series: 

    https://gorails.com/series/rails-concepts 

    1. 基本都是免费的
    2. 一些细小的知识点,很有帮助。
        
    • URL和parameter 的简单解析
    • 做一个app template
    • 使用 Ruby on Rails 的❌页面debug
    • rails5的actioncable和websockets介绍(有多个系列的cable视频)
    • Form的submit方法解释:params[:commit] == value
    • 记录关联中的选项:counter_cache


    URL和parameter 的简单解析。

    http://localhost:3000/products?test=111 

    在routes.rb中

    get '/products', to: "products#indx" 

    Rails routes会解析url,提取一个参数: params[:test] = 111 

    这个参数传给controller中的 Product#index:

    @test =  params[:test]

    在views/products/index.html.erb写:

    <%= @test%> 

    最后会在web page 上显示。 

    http://localhost:3000/products/dd?test=111

    在routes.rb中

    get '/products', to: "products#index" 

    get '/products/id', to: 'products#show' 

    Rails routes会解析url,提取2个参数: id和test

    这个2参数传给controller中的 Product#show:

    @test =  params[:test]

    @id = params[:id] 

    在views/products/index.html.erb写:

    <%= @test%> <%= @id%>

    最后会在web page 上显示这2个参数

    在termiinal的log上,会出现:Parameters: {"test" => "111",  "id" => "dd"} 



     

    做一个app template

    Rails指导: 

     http://guides.rubyonrails.org/generators.html#application-templates

    (一点感悟,光看指导,看不明白,理解不清楚。还是视频比较好,有step to step。方便理解) 

    视频教程:

    https://gorails.com/episodes/rails-application-templates?autoplay=1 

    教程案例:本地:/自我练习/jumpstart-master/whatever 

    ⚠️,不难理解,但是有很多兼容性等问题,需要测试模版是否好使。所以使用现成的模版稍微修改比较好。 


    基础:

    使用-m参数建立一个预制自定义gem的Rails app。 

    rails new myapp -m template.rb 

    下载git上的zip压缩包, Download ZIP,  解压缩后在,那个文件夹运行上面的命令。 

    也可以使用线上模版如:

    rails new myapp -m https://raw.github.com/80percent/rails-template/master/composer.rb

    打开模版设置的文件的命令是:atom template.rb 

    文档的理解:

    先设定方法:

    1. 定义add_template_repository_to_source_path
    2. 定义add_gems,即所要增加的gem
    3. 定义set_application_name
    4. 每个gem各自的设置,都需要定义。比如devise,需要def add_users, 挺复杂的,需要根据各自的gem使用文档来设置。
    5. 其他一些相关设置,比如打开spring。
    6. 执行上面的方法。在add_gems后,使用after_bundle(&block), 结束。
    after_bundle do
      set_application_name
      stop_spring
      add_users
     ...略
      add_announcements
      add_notifications
      add_multiple_authentication
      add_friendly_id
      copy_templates
      # Migrate
      rails_command "db:create"
      rails_command "db:migrate"
      # Migrations must be done before this
      add_administrate
      add_whenever
      add_sitemap
      git :init
      git add: "."
      git commit: %Q{ -m 'Initial commit' }
    end


    如何使用 Ruby on Rails 的❌页面debug

    弹出红色页面:

    首先要看标题,和标题下的解释。页面最下方有控制台,可以进行变量的输入测试反馈。

    如果不能找到问题。则需要看下面的一大堆stack tracks。 

    例子

    actionpack(3.2.8) lib/action_controller/metal/data_streaming.rb:125:in 'send_file_headers!'

    。。。略。。一堆

    app/controllers/charges_chntroller.rb:13:in 'block (2 levels) in show'

    ... 


    第一行actionpack(3.2.8) ...,指actionpack的版本,及出错的文件位置。这是源代码库的代码。往下看,找到自己写的代码的文件app/controllers/..., 然后回到atom查看细节。

    如果你怀疑这是一个方法使用的错误,看看是否用错参数及其格式。可以去API上查询此方法的详细信息。 

    还是找不到问题的话,并猜测是否是actionpack版本过期了?

    可以去git上rails/rails, 找对应的版本分支,根据文件路径打开对应的文件,并定位。

    右上角有一个blame按钮,可以查看这行代码之前的变更记录。

    总之,报错页的的标题,是可以定位bug,比如通过复制粘到google上查询类似问题,比较注重速度和效率。但查stack track才能够最准确的定位问题。这叫做读你的代码的故事。

    如果询问别人问题,把stack track粘贴上,很重要。 

    第一步,看错误标题及相关。这通常可以有效率解决问题,如果不能看第二步⬇️。

    第二步,通过stack track看最后列出的你写的code。 并确认是否是正确的。如果还不能解决问题。见第三步⬇️。

    第三步, 查看源代码库,通过第一行的版本和路径查看。 



    什么是webstocket和actioncable 

    之前学习的博客:http://www.cnblogs.com/chentianwei/p/8690304.html

    这章节过于基础,我需要一个完整的,最好是实际的产品的教学。看下面系列2. 

    有2个系列:



    Rails Forms with Multiple Submit Buttons 

    讲解ActionView::Helpers::Formbuilder#submit(value =nil, options={}) 

    还有一个submit_tag(value = "提交", options={}) 

    submit方法会根据对象是否是new而在controller中选择是create还是update。

    另外,开发者可以根据value的值,定义不同的额外行为。例子见下: 

    ⚠️解析成HTML,input标签内有name, value,2个特性:

    submit_tag "Complete sale", data: { disable_with: "Submitting..." }
    # => <input name="commit" data-disable-with="Submitting..." type="submit" value="Complete sale" />

    这2个特性组成了,在点击提交按钮后,request中的参数之一: {..., "commit" => "提交"}

    因此,params[:commit] 的值是"提交"。 根据value的不同,可以在同一个表格使用多个按钮, 并在controller中,设定针对不同value的不同方法。 

    比如,在创建或者更新的web页面,在“发布”按钮旁边增加一个“不发布“按钮。这两个按钮都会创建或更新一个记录,但会根据value,进行后续的行为,这里可以在index的页面隐藏“不发布”的记录。 

    button,button_tag方法和submit方法的相似和区别:

    •  都可以作为提交按钮,默认设置 type="submit"
    •  button可以接受一个块参数。type特性可以设置其他类型,如"reset" 或者javascript。


    Active Record Associations中的:counter_cache

    前置知识:

    Controlling caching:

    第一次从关联对象来查询数据,是从数据库中查询,查询结果会存储在缓存中。方便之后直接从缓存查询,速度提高。

    但有时候数据库更新太快。因此更新缓存, 使用reload方法。

    1. author.books  #从数据库取查询记录books
    2. author.books.size #从cache中得到
    3. author.books.reload.empty? #丢弃cache,从数据库取数据。 

    Controlling Association Scope 

    默认的关联对象之间是处于同一个模型module的scope范围。但例外是:如果两个对象定义在不同的scopes中,关联会失效,这是必须指定class_name ,明确说明属于哪个模型的类。 

    案例见:http://guides.rubyonrails.org/association_basics.html#tips-tricks-and-warnings

    另外,也可以用于自定义一个关联的对象名字,然后用class_name说明关联的真正类。 

     

    module MyApplication
      module Business
        class Supplier < ApplicationRecord
          has_one :account,
            class_name: "MyApplication::Billing::Account"
        end
      end
     
      module Billing
        class Account < ApplicationRecord
          belongs_to :supplier,
            class_name: "MyApplication::Business::Supplier"
        end
      end
    end

     Bi-directional Associations  双向关联

    默认简单的两个模型的关联,当一条记录的属性被改变,但没储存到数据库,关联记录是可以从缓存中得到这个改变的属性的。

    a = Author.first

    b = a.books.first

    a.first_name == b.author.first_name  返回true

    a.first_name = "David" #没有保存到数据库,只是保存到缓存了。

    a.first_name == b.author.first_name   从缓存中进行比较,返回true 

    但是如果关联包含scope或者如:through, :foreign_key 等选项,

    即间接的关联 ,则 

     a.first_name == b.author.first_name 返回false

    可以使用inverse_of选项,来建立bi-directional 关联:

    如:

    class Author < ApplicationRecord

      has_many :books, inverse_of: "writer"

    end

    class Book < ApplicationRecord

      belongs_to :writer, class_name: "Author", foreign_key: "author_id"

    end 


    counter_cache 

    查询@author.books.size的值,通过执行数据库语法COUNT(*) query.

    但无需每次都调用数据库。比如用在微博主页,每个大vip有多少粉丝。 对非时效性和准确性的数据,可以降准提速。

    在belongs_to上加上选项counter_cache:true,Rails会把缓存的value更新到数据库,然后返回这个值来响应size方法。

    ⚠️, 在Author上需要有一个column  books_count 

    (类名_count) 

    我的理解:第一次调用@author.books.size,会使用数据库计算,并存入books_count,下次再用就从books_count中调用数据了。 

    另外可以使用counter_cache: :自定义名字,来替代true,然后在has_many的表中定义这个名字作为列名。 

    class Book < ApplicationRecord
      belongs_to :author, counter_cache: true
    end
    class Author < ApplicationRecord
      has_many :books
    end

    这样,如果增加了一条Book记录,会自动更新Author中对应的author.books_count。

    同样,如何删除一条Book记录,也会自步更新author.books_count的数量,-1. 


    ActiveRecord::CounterCache::ClassMethods

    有一个reset_counters方法, 一般用于重置。

    比如以前没有使用counter_cache,现在已经有了一堆相关的记录。可以:

    rails g migration addXXX,然后在db/migrate/XXX_add_xxx中添加:

    add_column :users, :forum_posts_count, :integer, default: 0, null: false

    User.find_each {|u| User.reset_counters(u.id, :forum_posts)} 

    数据量非常大的时候,加上 batch_size: 1000

    find_each(batch_size: 1000) do ...end 

    或者使用原始SQL语法: 

    execute <<-SQL.squish 

    update users set forum_posts_count = (

          select count(1) from forum_posts where forum_posts.user_id = users.id 



  • 相关阅读:
    新的开始
    react的setState使用中遇到的问题
    h5的input的required使用中遇到的问题
    vue学习中v-if和v-show一起使用的问题
    异步 JavaScript 之 macrotask、microtask
    .eslintrc 文件
    Vue2学习结合bootstrapTable遇到的问题
    Vue2学习(3)
    ES6 箭头函数
    Vue2学习(2)
  • 原文地址:https://www.cnblogs.com/chentianwei/p/9258155.html
Copyright © 2011-2022 走看看