ruby rails + grape 的active record练习02

1、grape

rails启动最先读取的是config/目录下的配置文件;

输入culr命令构建的url  (-d:参数, -H:header ):

curl -X POST -d '{"author_name": "aaaaaa","article":{"title": "bbbbbbb", "content": "ccccccccccccc"}}' 'http://localhost:3000/v1/articles' -H Content-Type:application/json

rails会去读取application.rb中的路径,得知API文件都在app/api/目录下:

require_relative 'boot'

require 'rails/all'

# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)

module GrapeTest
  class Application < Rails::Application
    # Initialize configuration defaults for originally generated Rails version.
    config.load_defaults 5.2

    # Settings in config/environments/* take precedence over those specified here.
    # Application configuration can go into files in config/initializers
    # -- all .rb files in that directory are automatically loaded after loading
    # the framework and any gems in your application.

    config.paths.add File.join('app', 'api'), glob: File.join('**', '*.rb')
	config.autoload_paths += Dir[Rails.root.join('app', 'api', '*')]

  end
end

读取routes.rb文件中的路由设置:

require 'sidekiq/web'
require "#{Rails.root}/app/api/base"
#require "#{Rails.root}/app/api/twi/twitter"

Rails.application.routes.draw do
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
	resources :articles

  	#mount Twitter::API => '/'
  	mount API::Base => '/'        # http://localhost:3000/

  	root :to => 'home#index'
	#mount Sidekiq::Web => '/sidekiq'

end

去app/api/目录下寻找mudule为API,class为Base的API文件,即base.rb文件:

require 'v1/v1_api'
#require 'twi/twitter'

module API
  class Base < Grape::API
    mount API::V1
    #mount Twitter::API
  end
end

Base又路由到了v1_api.rb文件中的V1 class:

# v1-api.rb
require "#{Rails.root}/app/api/v1/helpers"

module API
  class V1 < Grape::API
    helpers BlogApi::HelpersV1

    format :json
    version 'v1', :using => :path
  
    default_error_status 400
    default_error_formatter :json

    #HardWorker.perform_async('bob', 5)

    resource :articles do

      desc "get all articles information"
      get do
        paginate_params = { :page => params[:page], :per_page => params[:per_page] || 20 }
        @articles = Article.includes(:author).paginate(paginate_params)
        present @articles
      end

      desc "return an artice"
      params do
        requires :id, :type => Integer, :desc => "artice id"
      end
      route_param :id do
        get do
          find_by_id params[:id]
          present @article
        end
      end

      desc "create an article"
      params do
        requires :author_name, type: String, desc: "author1's name"
        requires :article, type: Hash, desc: "article's attributes"
      end
      post do
        authenticate!
        @author =  Author.find_or_create_by(:name => params[:author_name])
        @article = Article.create(params[:article].merge(:author_id => @author.id))
        valid_with_present
      end

      desc "update an exist article"
      params do
        optional :author_name, type: String, desc: "a newer name"
        requires :article, type: Hash, desc: "updated attributes"
      end
      put ':id' do
        authenticate!
        find_by_id params[:id]

        if params[:author_name]
          @author =  Author.find_or_create_by(:name => params[:author_name])
          @article.update_attributes(params[:article].merge(:author_id => @author.id))
        else
          @article.update_attributes(params[:article])
        end

        valid_with_present
      end

      desc "delete an article"
      params do
        requires :id, type: Integer, desc: "article id"
      end
      delete ':id' do
        authenticate!
        find_by_id params[:id]
        @article.destroy

        if @article.persisted?
          error!({ :error => 'delete article failed' }, 400)
        else
          true
        end
      end

    end
  end
end

版本号v1和resource :articles加入到url中:http://localhost:3000/v1/articles

然后在该目录下寻找post动作:

desc "create an article"
      params do
        requires :author_name, type: String, desc: "author1's name"
        requires :article, type: Hash, desc: "article's attributes"
      end
      post do
        authenticate!
        @author =  Author.find_or_create_by(:name => params[:author_name])
        @article = Article.create(params[:article].merge(:author_id => @author.id))
        valid_with_present
      end

2、active record

读post动作的源码可以看出,需要的参数分别是author_name和hash类型的article,在curl中已经给出参数了,然后需要在Author模型中获取author_name=params(author_name)的author的信息,然后根据 author_name 和 article 创建一份新的article,其中都有对数据库表的查询和创建操作;

2.1、创建数据库

数据库配置文件config/database.yml:


#
default: &default
  adapter: mysql2
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  timeout: 5000
  username: root
  password: 'ur password'

development:
  <<: *default
  database: twi

# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
  <<: *default
  database: twi_test

production:
  <<: *default
  database: twi_pro

rails读取database.yml中的数据库配置,连接指定的数据库并且指定不同环境下的数据库名称,运行以下两个命令创建数据库:

> rails db:create
> rails db:migrate

或者

> rake db:create
> rake db:migrate

运行结果是: 数据库中多了两个数据库twi和twi_test;

2.2、用active reaord迁移创建数据库表

Active Record 迁移

运行migrate命令:

> rails generate migration CreateArticles title:string content:text author_id:integer created_at:datetime updated_at:datetime

> rails generate migration CreateAuthors name:string created_at:datetime uodated_at:datetime

 

Running via Spring preloader in process 20708
      invoke  active_record
   create    db/migrate/20190319061333_create_articles.rb

结果是:在db/migrate目录下多出来两个迁移文件,在db/下多出schema.rb文件:

# 20190319061303_create_authors.rb

class CreateAuthors < ActiveRecord::Migration[5.2]
  def change
    create_table :authors do |t|
      t.string :name
      t.datetime :created_at
      t.datetime :uodated_at
    end
  end
end
# 20190319061333_create_articles.rb

class CreateArticles < ActiveRecord::Migration[5.2]
  def change
    create_table :articles do |t|
      t.string :title
      t.text :content
      t.integer :author_id
      t.datetime :created_at
      t.datetime :updated_at
    end
  end
end
# schema.rb


# This file is auto-generated from the current state of the database. Instead
# of editing this file, please use the migrations feature of Active Record to
# incrementally modify your database, and then regenerate this schema definition.
#
# Note that this schema.rb definition is the authoritative source for your
# database schema. If you need to create the application database on another
# system, you should be using db:schema:load, not running all the migrations
# from scratch. The latter is a flawed and unsustainable approach (the more migrations
# you'll amass, the slower it'll run and the greater likelihood for issues).
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema.define(version: 2019_03_19_061333) do

  create_table "articles", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
    t.string "title"
    t.text "content"
    t.integer "author_id"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  create_table "authors", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
    t.string "name"
    t.datetime "created_at"
    t.datetime "uodated_at"
  end

  create_table "status", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
    t.string "user", limit: 30
    t.string "text"
  end

  create_table "statuses", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
    t.string "user", limit: 30
    t.string "text"
  end

  create_table "users", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
    t.string "first_name"
    t.string "last_name"
  end

end

迁移文件用来创建和change数据库和数据库表,chema.rb文件用来描述数据库表的chema:

之后运行rails提供的两个命令来运行迁移:

> rails db:migrate

结果就是在数据库twi中创建了数据库表authors和articles;

2.3、创建Orm model 用来对数据库表进行CRUD操作

ActiveRecord根据'多约定少配置'的原则(Active Record 基础),使得model和数据库表进行映射(ORM),model文件:

# author.rb


class Author < ActiveRecord::Base
  has_many :articles, :dependent => :destroy

  validates :name, :presence => true, :uniqueness => true
end
# article.rb

class Article < ActiveRecord::Base
  belongs_to :author

  validates :title, :presence => true
  # validates :author_id, :presence => true
  
  def to_hash
    {
      :title => title,
      :content => content,
      :author_id => author.try(:id)
    }
  end

  def author_name
    author.try(:name)
  end

  def author_name=(name)
    unless name.blank?
      author = Author.find_or_create_by(:name => name)
      self.author = author
      author.name
    end
  end
end

在API中,不直接对数据库表进行操作,而是操作表的映射模型,使用Author和Article对数据库进行CRUD,回到v1_api.rb。

Active Record 基础中介绍了用model对表进行CRUD操作的方法。

3、test

> curl -X POST -d '{"author_name": "aaaaaa","article":{"title": "bbbbbbb", "content": "ccccccccccccc"}}' 'http://localhost:3000/v1/articles' -H Content-Type:application/json

{"id":4,"title":"bbbbbbb","content":"ccccccccccccc","author_id":3,"created_at":"2019-03-19T08:01:52.000Z","updated_at":"2019-03-19T08:01:52.000Z"}%
> curl -X GET 'http://localhost:3000/v1/articles/1'

{"id":1,"title":"haha","content":"88 characters","author_id":1,"created_at":"2019-03-19T06:16:47.000Z","updated_at":"2019-03-19T06:16:47.000Z"}%

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值