├── .rspec ├── .coveralls.yml ├── lib ├── kintone │ ├── version.rb │ ├── type │ │ ├── extension │ │ │ ├── object.rb │ │ │ ├── enumerable.rb │ │ │ └── hash.rb │ │ └── record.rb │ ├── type.rb │ ├── command │ │ ├── app.rb │ │ ├── form.rb │ │ ├── preview_form.rb │ │ ├── app_acl.rb │ │ ├── space_body.rb │ │ ├── field_acl.rb │ │ ├── record_acl.rb │ │ ├── apps.rb │ │ ├── space_guests.rb │ │ ├── space.rb │ │ ├── bulk_request.rb │ │ ├── guests.rb │ │ ├── file.rb │ │ ├── space_members.rb │ │ ├── space_thread.rb │ │ ├── template_space.rb │ │ ├── apis.rb │ │ ├── record.rb │ │ ├── records.rb │ │ └── accessor.rb │ ├── command.rb │ ├── kintone_error.rb │ ├── query │ │ └── extension.rb │ ├── api │ │ └── guest.rb │ ├── query.rb │ └── api.rb └── kintone.rb ├── Gemfile ├── spec ├── spec_helper.rb └── kintone │ ├── command │ ├── preview_form_spec.rb │ ├── form_spec.rb │ ├── app_acl_spec.rb │ ├── space_body_spec.rb │ ├── app_spec.rb │ ├── field_acl_spec.rb │ ├── record_acl_spec.rb │ ├── space_guests_spec.rb │ ├── template_space_spec.rb │ ├── file_spec.rb │ ├── space_thread_spec.rb │ ├── space_spec.rb │ ├── bulk_request_spec.rb │ ├── apps_spec.rb │ ├── guests_spec.rb │ ├── space_members_spec.rb │ ├── apis_spec.rb │ ├── record_spec.rb │ └── records_spec.rb │ ├── type │ └── record_spec.rb │ ├── kintone_error_spec.rb │ ├── api │ └── guest_spec.rb │ ├── api_spec.rb │ └── query_spec.rb ├── Rakefile ├── .gitignore ├── Guardfile ├── .travis.yml ├── LICENSE.txt ├── .rubocop.yml ├── kintone.gemspec └── README.md /.rspec: -------------------------------------------------------------------------------- 1 | -c -f doc 2 | -------------------------------------------------------------------------------- /.coveralls.yml: -------------------------------------------------------------------------------- 1 | repo_token: zDaEBy037OST98voxtIsbOPpyrTkqUXxi -------------------------------------------------------------------------------- /lib/kintone/version.rb: -------------------------------------------------------------------------------- 1 | module Kintone 2 | VERSION = '0.1.5'.freeze 3 | end 4 | -------------------------------------------------------------------------------- /lib/kintone/type/extension/object.rb: -------------------------------------------------------------------------------- 1 | class Object 2 | def to_kintone 3 | self 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # Specify your gem's dependencies in kintone.gemspec 4 | gemspec 5 | -------------------------------------------------------------------------------- /lib/kintone/type/extension/enumerable.rb: -------------------------------------------------------------------------------- 1 | module Enumerable 2 | def to_kintone 3 | map(&:to_kintone) 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /lib/kintone/type/extension/hash.rb: -------------------------------------------------------------------------------- 1 | class Hash 2 | def to_kintone 3 | map { |k, v| [k, v.to_kintone] }.to_h 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /lib/kintone.rb: -------------------------------------------------------------------------------- 1 | require 'kintone/version' 2 | require 'kintone/api' 3 | require 'kintone/type' 4 | 5 | module Kintone 6 | # Your code goes here... 7 | end 8 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | require 'rubygems' 2 | require 'kintone' 3 | require 'webmock/rspec' 4 | require 'rspec-parameterized' 5 | require 'coveralls' 6 | 7 | Coveralls.wear! 8 | -------------------------------------------------------------------------------- /lib/kintone/type.rb: -------------------------------------------------------------------------------- 1 | require 'kintone/type/extension/object' 2 | require 'kintone/type/extension/enumerable' 3 | require 'kintone/type/extension/hash' 4 | require 'kintone/type/record' 5 | 6 | module Kintone::Type; end 7 | -------------------------------------------------------------------------------- /lib/kintone/command/app.rb: -------------------------------------------------------------------------------- 1 | require 'kintone/command' 2 | 3 | class Kintone::Command::App < Kintone::Command 4 | def self.path 5 | 'app' 6 | end 7 | 8 | def get(id) 9 | @api.get(@url, id: id) 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /lib/kintone/command.rb: -------------------------------------------------------------------------------- 1 | require 'kintone/api' 2 | 3 | class Kintone::Command 4 | def self.path 5 | '/' 6 | end 7 | 8 | def initialize(api) 9 | @api = api 10 | @url = @api.get_url(self.class.path) 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /lib/kintone/command/form.rb: -------------------------------------------------------------------------------- 1 | require 'kintone/command' 2 | 3 | class Kintone::Command::Form < Kintone::Command 4 | def self.path 5 | 'form' 6 | end 7 | 8 | def get(app) 9 | @api.get(@url, app: app) 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /lib/kintone/command/preview_form.rb: -------------------------------------------------------------------------------- 1 | require 'kintone/command' 2 | 3 | class Kintone::Command::PreviewForm < Kintone::Command 4 | def self.path 5 | 'preview/form' 6 | end 7 | 8 | def get(app) 9 | @api.get(@url, app: app) 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'bundler/gem_tasks' 2 | require 'rspec/core/rake_task' 3 | require 'rubocop/rake_task' 4 | 5 | RSpec::Core::RakeTask.new 6 | RuboCop::RakeTask.new 7 | 8 | task default: :travis 9 | task travis: [:spec, :rubocop] 10 | task test: [:spec, :rubocop] 11 | -------------------------------------------------------------------------------- /lib/kintone/command/app_acl.rb: -------------------------------------------------------------------------------- 1 | require 'kintone/command' 2 | 3 | class Kintone::Command::AppAcl < Kintone::Command 4 | def self.path 5 | 'app/acl' 6 | end 7 | 8 | def update(app, rights) 9 | @api.put(@url, app: app, rights: rights) 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /lib/kintone/command/space_body.rb: -------------------------------------------------------------------------------- 1 | require 'kintone/command' 2 | 3 | class Kintone::Command::SpaceBody < Kintone::Command 4 | def self.path 5 | 'space/body' 6 | end 7 | 8 | def update(id, body) 9 | @api.put(@url, id: id, body: body) 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /lib/kintone/command/field_acl.rb: -------------------------------------------------------------------------------- 1 | require 'kintone/command' 2 | 3 | class Kintone::Command::FieldAcl < Kintone::Command 4 | def self.path 5 | 'field/acl' 6 | end 7 | 8 | def update(id, rights) 9 | @api.put(@url, id: id, rights: rights) 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /lib/kintone/command/record_acl.rb: -------------------------------------------------------------------------------- 1 | require 'kintone/command' 2 | 3 | class Kintone::Command::RecordAcl < Kintone::Command 4 | def self.path 5 | 'record/acl' 6 | end 7 | 8 | def update(id, rights) 9 | @api.put(@url, id: id, rights: rights) 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /lib/kintone/command/apps.rb: -------------------------------------------------------------------------------- 1 | require 'kintone/command' 2 | 3 | class Kintone::Command::Apps < Kintone::Command 4 | def self.path 5 | 'apps' 6 | end 7 | 8 | def get(params = {}) 9 | response = @api.get(@url, params) 10 | response['apps'] 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /lib/kintone/command/space_guests.rb: -------------------------------------------------------------------------------- 1 | require 'kintone/command' 2 | 3 | class Kintone::Command::SpaceGuests < Kintone::Command 4 | def self.path 5 | 'space/guests' 6 | end 7 | 8 | def update(id, guests) 9 | @api.put(@url, id: id, guests: guests) 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | *.rbc 3 | .bundle 4 | .config 5 | .yardoc 6 | Gemfile.lock 7 | InstalledFiles 8 | _yardoc 9 | coverage 10 | doc/ 11 | lib/bundler/man 12 | pkg 13 | rdoc 14 | spec/reports 15 | test/tmp 16 | test/version_tmp 17 | tmp 18 | vendor/ 19 | sample/ 20 | .ruby-version 21 | .rbenv-gemsets 22 | -------------------------------------------------------------------------------- /lib/kintone/type/record.rb: -------------------------------------------------------------------------------- 1 | module Kintone::Type 2 | class Record < Hash 3 | def initialize(default = nil) 4 | default.each { |k, v| store(k, v) } if default.is_a?(Hash) 5 | end 6 | 7 | def to_kintone 8 | map { |k, v| [k, { value: v }] }.to_h 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /lib/kintone/command/space.rb: -------------------------------------------------------------------------------- 1 | require 'kintone/command' 2 | 3 | class Kintone::Command::Space < Kintone::Command 4 | def self.path 5 | 'space' 6 | end 7 | 8 | def get(id) 9 | @api.get(@url, id: id) 10 | end 11 | 12 | def delete(id) 13 | @api.delete(@url, id: id) 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /lib/kintone/command/bulk_request.rb: -------------------------------------------------------------------------------- 1 | require 'kintone/command' 2 | 3 | class Kintone::Command::BulkRequest < Kintone::Command 4 | def self.path 5 | 'bulkRequest' 6 | end 7 | 8 | def request(requests) 9 | response = @api.post(@url, requests: requests) 10 | response['results'] 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /lib/kintone/command/guests.rb: -------------------------------------------------------------------------------- 1 | require 'kintone/command' 2 | 3 | class Kintone::Command::Guests < Kintone::Command 4 | def self.path 5 | 'guests' 6 | end 7 | 8 | def register(guests) 9 | @api.post(@url, guests: guests) 10 | end 11 | 12 | def delete(guests) 13 | @api.delete(@url, guests: guests) 14 | end 15 | 16 | alias create register 17 | end 18 | -------------------------------------------------------------------------------- /lib/kintone/command/file.rb: -------------------------------------------------------------------------------- 1 | require 'kintone/command' 2 | 3 | class Kintone::Command::File < Kintone::Command 4 | def self.path 5 | 'file' 6 | end 7 | 8 | def get(file_key) 9 | @api.get(@url, fileKey: file_key) 10 | end 11 | 12 | def register(path, content_type, original_filename) 13 | @api.post_file(@url, path, content_type, original_filename) 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /lib/kintone/command/space_members.rb: -------------------------------------------------------------------------------- 1 | require 'kintone/command' 2 | 3 | class Kintone::Command::SpaceMembers < Kintone::Command 4 | def self.path 5 | 'space/members' 6 | end 7 | 8 | def get(id) 9 | response = @api.get(@url, id: id) 10 | response['members'] 11 | end 12 | 13 | def update(id, members) 14 | @api.put(@url, id: id, members: members) 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /lib/kintone/command/space_thread.rb: -------------------------------------------------------------------------------- 1 | require 'kintone/command' 2 | 3 | class Kintone::Command::SpaceThread < Kintone::Command 4 | def self.path 5 | 'space/thread' 6 | end 7 | 8 | def update(id, name: nil, body: nil) 9 | request_body = { id: id } 10 | request_body[:name] = name if name 11 | request_body[:body] = body if body 12 | @api.put(@url, request_body) 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /Guardfile: -------------------------------------------------------------------------------- 1 | guard :rspec, all_after_pass: false, all_on_start: false, cmd: 'rspec' do 2 | watch(%r{spec/.+_spec\.rb$}) 3 | watch(%r{lib/(.+)\.rb$}) {|m| "spec/#{m[1]}_spec.rb"} 4 | watch(%r{lib/(.+)/.+\.rb$}) {|m| "spec/#{m[1]}_spec.rb"} 5 | end 6 | 7 | guard :rubocop, all_on_start: false, cmd: 'rubocop' do 8 | watch(%r{.+\.rb$}) 9 | watch(%r{(?:.+/)?\.rubocop\.yml$}) { |m| File.dirname(m[0]) } 10 | end 11 | -------------------------------------------------------------------------------- /lib/kintone/command/template_space.rb: -------------------------------------------------------------------------------- 1 | require 'kintone/command' 2 | 3 | class Kintone::Command::TemplateSpace < Kintone::Command 4 | def self.path 5 | 'template/space' 6 | end 7 | 8 | def create(id, name, members, is_guest: false, fixed_member: false) 9 | body = { id: id, name: name, members: members, isGuest: is_guest, fixedMember: fixed_member } 10 | @api.post(@url, body) 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /lib/kintone/kintone_error.rb: -------------------------------------------------------------------------------- 1 | class Kintone::KintoneError < StandardError 2 | attr_reader :message_text, :id, :code, :http_status, :errors 3 | 4 | def initialize(messages, http_status) 5 | @message_text = messages['message'] 6 | @id = messages['id'] 7 | @code = messages['code'] 8 | @errors = messages['errors'] 9 | @http_status = http_status 10 | super(format('%s [%s] %s(%s)', @http_status, @code, @message_text, @id)) 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /lib/kintone/query/extension.rb: -------------------------------------------------------------------------------- 1 | class Kintone::Query 2 | module Extention 3 | refine Object do 4 | def query_format 5 | self 6 | end 7 | end 8 | 9 | refine Symbol do 10 | def query_format 11 | "\"#{self}\"" 12 | end 13 | end 14 | 15 | refine String do 16 | def query_format 17 | if self =~ /\A".+"\z/ then self 18 | else "\"#{self}\"" 19 | end 20 | end 21 | end 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /lib/kintone/command/apis.rb: -------------------------------------------------------------------------------- 1 | require 'kintone/command' 2 | 3 | class Kintone::Command::Apis < Kintone::Command 4 | def self.path 5 | 'apis' 6 | end 7 | 8 | def get 9 | @api.get(@url) 10 | end 11 | 12 | def get_details_of(link) 13 | url = Kintone::Api::BASE_PATH + link 14 | @api.get(url) 15 | end 16 | 17 | def get_details_of_key(key) 18 | response = get 19 | link = response['apis'][key]['link'] 20 | get_details_of(link) 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /lib/kintone/command/record.rb: -------------------------------------------------------------------------------- 1 | require 'kintone/command' 2 | 3 | class Kintone::Command::Record < Kintone::Command 4 | def self.path 5 | 'record' 6 | end 7 | 8 | def get(app, id) 9 | @api.get(@url, app: app, id: id) 10 | end 11 | 12 | def register(app, record) 13 | @api.post(@url, app: app, record: record.to_kintone) 14 | end 15 | 16 | def update(app, id, record, revision: nil) 17 | body = { app: app, id: id, record: record.to_kintone } 18 | body[:revision] = revision if revision 19 | @api.put(@url, body) 20 | end 21 | 22 | alias create register 23 | end 24 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: ruby 3 | rvm: 4 | - 2.1.0 5 | - 2.1.1 6 | - 2.1.2 7 | - 2.1.3 8 | - 2.1.4 9 | - 2.1.5 10 | - 2.1.6 11 | - 2.1.7 12 | - 2.1.8 13 | - 2.1.9 14 | - 2.1.10 15 | - 2.2.0 16 | - 2.2.1 17 | - 2.2.2 18 | - 2.2.3 19 | - 2.2.4 20 | - 2.2.5 21 | - 2.2.6 22 | - 2.2.7 23 | - 2.2.8 24 | - 2.2.9 25 | - 2.2.10 26 | - 2.3.0 27 | - 2.3.1 28 | - 2.3.2 29 | - 2.3.3 30 | - 2.3.4 31 | - 2.3.5 32 | - 2.3.6 33 | - 2.3.7 34 | - 2.4.0 35 | - 2.4.1 36 | - 2.4.2 37 | - 2.4.3 38 | - 2.4.4 39 | - 2.5.0 40 | - 2.5.1 41 | before_install: 42 | - gem update bundler 43 | - gem install rainbow 44 | -------------------------------------------------------------------------------- /lib/kintone/command/records.rb: -------------------------------------------------------------------------------- 1 | require 'kintone/command' 2 | 3 | class Kintone::Command::Records < Kintone::Command 4 | def self.path 5 | 'records' 6 | end 7 | 8 | def get(app, query, fields, total_count: false) 9 | params = { app: app, query: query.to_s, totalCount: total_count } 10 | params[:fields] = fields unless fields.nil? 11 | @api.get(@url, params) 12 | end 13 | 14 | def register(app, records) 15 | @api.post(@url, app: app, records: records.to_kintone) 16 | end 17 | 18 | def update(app, records) 19 | @api.put(@url, app: app, records: records.to_kintone) 20 | end 21 | 22 | def delete(app, ids, revisions: nil) 23 | params = { app: app, ids: ids } 24 | params[:revisions] = revisions if revisions 25 | @api.delete(@url, params) 26 | end 27 | 28 | alias create register 29 | end 30 | -------------------------------------------------------------------------------- /spec/kintone/command/preview_form_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | require 'kintone/command/preview_form' 3 | require 'kintone/api' 4 | 5 | describe Kintone::Command::PreviewForm do 6 | let(:target) { Kintone::Command::PreviewForm.new(api) } 7 | let(:api) { Kintone::Api.new('example.cybozu.com', 'Administrator', 'cybozu') } 8 | 9 | describe '#get' do 10 | before(:each) do 11 | stub_request( 12 | :get, 13 | 'https://example.cybozu.com/k/v1/preview/form.json' 14 | ) 15 | .with(body: request_body.to_json) 16 | .to_return( 17 | body: '{"result":"ok"}', 18 | status: 200, 19 | headers: { 'Content-type' => 'application/json' } 20 | ) 21 | end 22 | 23 | subject { target.get(app) } 24 | 25 | let(:app) { 1 } 26 | let(:request_body) { { app: app } } 27 | 28 | it { expect(subject).to eq 'result' => 'ok' } 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /spec/kintone/type/record_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | require 'kintone/type/record' 3 | 4 | describe Kintone::Type::Record do 5 | let(:target) { Kintone::Type::Record.new } 6 | 7 | describe '#to_kitnone' do 8 | subject { target.to_kintone } 9 | 10 | context 'データが登録されているとき' do 11 | before(:each) do 12 | target[:a] = 1 13 | target[:b] = 2 14 | end 15 | 16 | it { expect(subject).to match a: { value: 1 }, b: { value: 2 } } 17 | end 18 | 19 | context 'データが登録されてないとき' do 20 | it { expect(subject).to be_empty } 21 | end 22 | 23 | context 'initializeで初期値を指定したとき' do 24 | let(:target) { Kintone::Type::Record.new(default) } 25 | 26 | where(:default, :result) do 27 | [ 28 | [{ a: 1, b: 2 }, { a: { value: 1 }, b: { value: 2 } }], 29 | [[[:a, 1], [:b, 2]], {}] 30 | ] 31 | end 32 | 33 | with_them do 34 | it { expect(subject).to match result } 35 | end 36 | end 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 Rikiya Kawakami 2 | 3 | MIT License 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /lib/kintone/api/guest.rb: -------------------------------------------------------------------------------- 1 | require 'forwardable' 2 | require 'kintone/api' 3 | require 'kintone/command/accessor' 4 | 5 | class Kintone::Api 6 | class Guest 7 | extend Forwardable 8 | 9 | GUEST_PATH = '/k/guest/%s/v1/'.freeze 10 | ACCESSIBLE_COMMAND = [ 11 | :record, :records, :form, :app_acl, :record_acl, 12 | :field_acl, :space, :space_body, :space_thread, :space_members, 13 | :space_guests, :app, :apps, :bulk_request, :bulk, 14 | :file, :preview_form 15 | ].freeze 16 | 17 | def_delegators :@api, :get, :post, :put, :delete, :post_file 18 | 19 | def initialize(space_id, api) 20 | @api = api 21 | @guest_path = GUEST_PATH % space_id.to_i 22 | end 23 | 24 | def get_url(command) 25 | @guest_path + (COMMAND % command) 26 | end 27 | 28 | def method_missing(name, *args) 29 | if ACCESSIBLE_COMMAND.include?(name) 30 | CommandAccessor.send(name, self) 31 | else 32 | super 33 | end 34 | end 35 | 36 | def respond_to_missing?(name, *args) 37 | ACCESSIBLE_COMMAND.include?(name) || super 38 | end 39 | 40 | class CommandAccessor 41 | extend Kintone::Command::Accessor 42 | end 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | # This configuration was generated by `rubocop --auto-gen-config` 2 | # on 2014-07-24 11:44:58 +0900 using RuboCop version 0.24.1. 3 | # The point is for the user to remove these configuration records 4 | # one by one as the offenses are removed from the code base. 5 | # Note that changes in the inspected code, or installation of new 6 | # versions of RuboCop, may require this file to be generated again. 7 | 8 | AllCops: 9 | Exclude: 10 | - 'Guardfile' 11 | - 'vendor/**/*' 12 | 13 | # Configuration parameters: EnforcedStyle, SupportedStyles. 14 | Style/ClassAndModuleChildren: 15 | EnforcedStyle: compact 16 | 17 | Style/Documentation: 18 | Enabled: false 19 | 20 | # Configuration parameters: AllowURI. 21 | Metrics/LineLength: 22 | Max: 1_00 23 | 24 | # Cop supports --auto-correct. 25 | # Configuration parameters: EnforcedStyle, SupportedStyles. 26 | Style/StringLiterals: 27 | EnforcedStyle: single_quotes 28 | 29 | Style/WordArray: 30 | Exclude: 31 | - 'spec/**/**' 32 | 33 | Style/AsciiComments: 34 | Enabled: false 35 | 36 | CyclomaticComplexity: 37 | Max: 10 38 | 39 | Style/FrozenStringLiteralComment: 40 | Enabled: false 41 | 42 | Style/SymbolProc: 43 | Exclude: 44 | - 'lib/kintone/query.rb' 45 | 46 | Style/SignalException: 47 | EnforcedStyle: only_raise 48 | -------------------------------------------------------------------------------- /kintone.gemspec: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | lib = File.expand_path('../lib', __FILE__) 3 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 4 | require 'kintone/version' 5 | 6 | Gem::Specification.new do |spec| 7 | spec.name = 'kintone' 8 | spec.version = Kintone::VERSION 9 | spec.authors = ['Rikiya Kawakami'] 10 | spec.email = ['ricky.k.yang@gmail.com'] 11 | spec.summary = 'kintone API client for Ruby.' 12 | spec.description = 'kintone API client for Ruby.' 13 | spec.homepage = 'https://github.com/jue58/kintone' 14 | spec.license = 'MIT' 15 | 16 | spec.files = `git ls-files -z`.split("\x0") 17 | spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } 18 | spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) 19 | spec.require_paths = ['lib'] 20 | 21 | spec.add_runtime_dependency 'faraday', '>=0.9.2' 22 | spec.add_runtime_dependency 'faraday_middleware', '>=0.10.0' 23 | 24 | spec.add_development_dependency 'bundler', '~> 1.5' 25 | spec.add_development_dependency 'rake' 26 | spec.add_development_dependency 'rspec', '~> 3' 27 | spec.add_development_dependency 'rubocop', '~> 0.44.1' 28 | spec.add_development_dependency 'webmock', '~> 2.3' 29 | spec.add_development_dependency 'rspec-parameterized', '~> 0.1.2' 30 | spec.add_development_dependency 'coveralls' 31 | end 32 | -------------------------------------------------------------------------------- /spec/kintone/command/form_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | require 'kintone/command/form' 3 | require 'kintone/api' 4 | 5 | describe Kintone::Command::Form do 6 | let(:target) { Kintone::Command::Form.new(api) } 7 | let(:api) { Kintone::Api.new('example.cybozu.com', 'Administrator', 'cybozu') } 8 | 9 | describe '#get' do 10 | before(:each) do 11 | stub_request( 12 | :get, 13 | 'https://example.cybozu.com/k/v1/form.json' 14 | ) 15 | .with(body: request_body.to_json) 16 | .to_return( 17 | body: '{"result":"ok"}', 18 | status: 200, 19 | headers: { 'Content-type' => 'application/json' } 20 | ) 21 | end 22 | 23 | subject { target.get(app) } 24 | 25 | let(:app) { 4 } 26 | let(:request_body) { { app: app } } 27 | 28 | it { expect(subject).to eq 'result' => 'ok' } 29 | 30 | context 'fail to request' do 31 | before(:each) do 32 | stub_request( 33 | :get, 34 | 'https://example.cybozu.com/k/v1/form.json' 35 | ) 36 | .with(body: request_body.to_json) 37 | .to_return( 38 | body: '{"message":"不正なJSON文字列です。","id":"1505999166-897850006","code":"CB_IJ01"}', 39 | status: 500, 40 | headers: { 'Content-type' => 'application/json' } 41 | ) 42 | end 43 | 44 | it { expect { subject }.to raise_error Kintone::KintoneError } 45 | end 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /spec/kintone/command/app_acl_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | require 'kintone/command/app_acl' 3 | require 'kintone/api' 4 | 5 | describe Kintone::Command::AppAcl do 6 | let(:target) { Kintone::Command::AppAcl.new(api) } 7 | let(:api) { Kintone::Api.new('example.cybozu.com', 'Administrator', 'cybozu') } 8 | 9 | describe '#update' do 10 | before(:each) do 11 | stub_request( 12 | :put, 13 | 'https://example.cybozu.com/k/v1/app/acl.json' 14 | ) 15 | .with(body: { 'app' => 1, 'rights' => { 'p1' => 'abc', 'p2' => 'def' } }.to_json) 16 | .to_return(body: '{}', status: 200, headers: { 'Content-type' => 'application/json' }) 17 | end 18 | 19 | subject { target.update(app, rights) } 20 | 21 | let(:app) { 1 } 22 | let(:rights) { { 'p1' => 'abc', 'p2' => 'def' } } 23 | 24 | it { expect(subject).to eq({}) } 25 | 26 | context 'fail to request' do 27 | before(:each) do 28 | stub_request( 29 | :put, 30 | 'https://example.cybozu.com/k/v1/app/acl.json' 31 | ) 32 | .with(body: { 'app' => 1, 'rights' => { 'p1' => 'abc', 'p2' => 'def' } }.to_json) 33 | .to_return( 34 | body: '{"message":"不正なJSON文字列です。","id":"1505999166-897850006","code":"CB_IJ01"}', 35 | status: 500, 36 | headers: { 'Content-Type' => 'application/json' } 37 | ) 38 | end 39 | 40 | it { expect { subject }.to raise_error Kintone::KintoneError } 41 | end 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /spec/kintone/command/space_body_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | require 'kintone/command/space_body' 3 | require 'kintone/api' 4 | 5 | describe Kintone::Command::SpaceBody do 6 | let(:target) { Kintone::Command::SpaceBody.new(api) } 7 | let(:api) { Kintone::Api.new('example.cybozu.com', 'Administrator', 'cybozu') } 8 | 9 | describe '#update' do 10 | before(:each) do 11 | stub_request( 12 | :put, 13 | 'https://example.cybozu.com/k/v1/space/body.json' 14 | ) 15 | .with(body: { id: 1, body: '総務課専用のスペースです。' }.to_json) 16 | .to_return( 17 | body: '{}', 18 | status: 200, 19 | headers: { 'Content-type' => 'application/json' } 20 | ) 21 | end 22 | 23 | subject { target.update(id, body) } 24 | 25 | let(:id) { 1 } 26 | let(:body) { '総務課専用のスペースです。' } 27 | 28 | it { expect(subject).to eq({}) } 29 | 30 | context 'fail to request' do 31 | before(:each) do 32 | stub_request( 33 | :put, 34 | 'https://example.cybozu.com/k/v1/space/body.json' 35 | ) 36 | .with(body: { id: 1, body: '総務課専用のスペースです。' }.to_json) 37 | .to_return( 38 | body: '{"message":"不正なJSON文字列です。","id":"1505999166-897850006","code":"CB_IJ01"}', 39 | status: 500, 40 | headers: { 'Content-Type' => 'application/json' } 41 | ) 42 | end 43 | 44 | it { expect { subject }.to raise_error Kintone::KintoneError } 45 | end 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /spec/kintone/command/app_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | require 'kintone/command/app' 3 | 4 | describe Kintone::Command::App do 5 | let(:target) { Kintone::Command::App.new(api) } 6 | let(:api) { Kintone::Api.new('example.cybozu.com', 'Administrator', 'cybozu') } 7 | 8 | describe '#get' do 9 | before(:each) do 10 | stub_request( 11 | :get, 12 | 'https://example.cybozu.com/k/v1/app.json' 13 | ) 14 | .with(body: { id: id }) 15 | .to_return( 16 | body: response_data.to_json, 17 | status: 200, 18 | headers: { 'Content-type' => 'application/json' } 19 | ) 20 | end 21 | 22 | subject { target.get(id) } 23 | 24 | let(:id) { 4 } 25 | 26 | def response_data 27 | { 28 | appId: '4', 29 | code: '', 30 | name: 'アプリ', 31 | description: 'よいアプリです' 32 | } 33 | end 34 | 35 | it { is_expected.to be_kind_of(Hash) } 36 | 37 | context 'fail to request' do 38 | before(:each) do 39 | stub_request( 40 | :get, 41 | 'https://example.cybozu.com/k/v1/app.json' 42 | ) 43 | .with(body: { id: id }) 44 | .to_return( 45 | body: '{"message":"不正なJSON文字列です。","id":"1505999166-897850006","code":"CB_IJ01"}', 46 | status: 500, 47 | headers: { 'Content-Type' => 'application/json' } 48 | ) 49 | end 50 | 51 | it { expect { subject }.to raise_error Kintone::KintoneError } 52 | end 53 | end 54 | end 55 | -------------------------------------------------------------------------------- /spec/kintone/command/field_acl_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | require 'kintone/command/field_acl' 3 | require 'kintone/api' 4 | 5 | describe Kintone::Command::FieldAcl do 6 | let(:target) { Kintone::Command::FieldAcl.new(api) } 7 | let(:api) { Kintone::Api.new('example.cybozu.com', 'Administrator', 'cybozu') } 8 | 9 | describe '#update' do 10 | before(:each) do 11 | stub_request( 12 | :put, 13 | 'https://example.cybozu.com/k/v1/field/acl.json' 14 | ) 15 | .with(body: { 'id' => 1, 'rights' => { 'p1' => 'abc', 'p2' => 'def' } }.to_json) 16 | .to_return( 17 | body: '{}', 18 | status: 200, 19 | headers: { 'Content-type' => 'application/json' } 20 | ) 21 | end 22 | 23 | let(:id) { 1 } 24 | let(:rights) { { 'p1' => 'abc', 'p2' => 'def' } } 25 | 26 | subject { target.update(id, rights) } 27 | 28 | it { expect(subject).to eq({}) } 29 | 30 | context 'fail to request' do 31 | before(:each) do 32 | stub_request( 33 | :put, 34 | 'https://example.cybozu.com/k/v1/field/acl.json' 35 | ) 36 | .with(body: { 'id' => 1, 'rights' => { 'p1' => 'abc', 'p2' => 'def' } }.to_json) 37 | .to_return( 38 | body: '{"message":"不正なJSON文字列です。","id":"1505999166-897850006","code":"CB_IJ01"}', 39 | status: 500, 40 | headers: { 'Content-Type' => 'application/json' } 41 | ) 42 | end 43 | 44 | it { expect { subject }.to raise_error Kintone::KintoneError } 45 | end 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /spec/kintone/command/record_acl_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | require 'kintone/command/record_acl' 3 | require 'kintone/api' 4 | 5 | describe Kintone::Command::RecordAcl do 6 | let(:target) { Kintone::Command::RecordAcl.new(api) } 7 | let(:api) { Kintone::Api.new('example.cybozu.com', 'Administrator', 'cybozu') } 8 | 9 | describe '#update' do 10 | before(:each) do 11 | stub_request( 12 | :put, 13 | 'https://example.cybozu.com/k/v1/record/acl.json' 14 | ) 15 | .with(body: request_body.to_json) 16 | .to_return( 17 | body: '{}', 18 | status: 200, 19 | headers: { 'Content-type' => 'application/json' } 20 | ) 21 | end 22 | 23 | subject { target.update(id, rights) } 24 | 25 | let(:id) { 1 } 26 | let(:rights) { { 'p1' => 'abc', 'p2' => 'def' } } 27 | let(:request_body) { { 'id' => 1, 'rights' => { 'p1' => 'abc', 'p2' => 'def' } } } 28 | 29 | it { expect(subject).to eq({}) } 30 | 31 | context 'fail to request' do 32 | before(:each) do 33 | stub_request( 34 | :put, 35 | 'https://example.cybozu.com/k/v1/record/acl.json' 36 | ) 37 | .with(body: request_body.to_json) 38 | .to_return( 39 | body: '{"message":"不正なJSON文字列です。","id":"1505999166-897850006","code":"CB_IJ01"}', 40 | status: 500, 41 | headers: { 'Content-Type' => 'application/json' } 42 | ) 43 | end 44 | 45 | it { expect { subject }.to raise_error Kintone::KintoneError } 46 | end 47 | end 48 | end 49 | -------------------------------------------------------------------------------- /spec/kintone/command/space_guests_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | require 'kintone/command/space_guests' 3 | require 'kintone/api' 4 | 5 | describe Kintone::Command::SpaceGuests do 6 | let(:target) { Kintone::Command::SpaceGuests.new(guest) } 7 | let(:guest) { api.guest(guest_id) } 8 | let(:guest_id) { 1 } 9 | let(:api) { Kintone::Api.new('example.cybozu.com', 'Administrator', 'cybozu') } 10 | 11 | describe '#update' do 12 | before(:each) do 13 | stub_request( 14 | :put, 15 | 'https://example.cybozu.com/k/guest/1/v1/space/guests.json' 16 | ) 17 | .with(body: { id: id, guests: guests }.to_json) 18 | .to_return( 19 | body: '{}', 20 | status: 200, 21 | headers: { 'Content-type' => 'application/json' } 22 | ) 23 | end 24 | 25 | subject { target.update(id, guests) } 26 | 27 | let(:id) { 10 } 28 | let(:guests) do 29 | [ 30 | 'guest1@example.com', 31 | 'guest2@example.com', 32 | 'guest3@example.com' 33 | ] 34 | end 35 | 36 | it { is_expected.to be_truthy } 37 | 38 | context 'fail to request' do 39 | before(:each) do 40 | stub_request( 41 | :put, 42 | 'https://example.cybozu.com/k/guest/1/v1/space/guests.json' 43 | ) 44 | .with(body: { id: id, guests: guests }.to_json) 45 | .to_return( 46 | body: '{"message":"不正なJSON文字列です。","id":"1505999166-897850006","code":"CB_IJ01"}', 47 | status: 500, 48 | headers: { 'Content-Type' => 'application/json' } 49 | ) 50 | end 51 | 52 | it { expect { subject }.to raise_error Kintone::KintoneError } 53 | end 54 | end 55 | end 56 | -------------------------------------------------------------------------------- /spec/kintone/command/template_space_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | require 'kintone/command/template_space' 3 | require 'kintone/api' 4 | 5 | describe Kintone::Command::TemplateSpace do 6 | let(:target) { Kintone::Command::TemplateSpace.new(api) } 7 | let(:api) { Kintone::Api.new('example.cybozu.com', 'Administrator', 'cybozu') } 8 | 9 | describe '#create' do 10 | before(:each) do 11 | stub_request( 12 | :post, 13 | 'https://example.cybozu.com/k/v1/template/space.json' 14 | ) 15 | .with(body: request_data.to_json) 16 | .to_return( 17 | body: '{"id":"1"}', 18 | status: 200, 19 | headers: { 'Content-type' => 'application/json' } 20 | ) 21 | end 22 | 23 | subject { target.create(id, name, members, is_guest: is_guest, fixed_member: fixed_member) } 24 | 25 | let(:id) { 1 } 26 | let(:name) { 'sample space' } 27 | let(:members) { [] } 28 | let(:is_guest) { false } 29 | let(:fixed_member) { false } 30 | let(:request_data) do 31 | { 32 | id: id, 33 | name: name, 34 | members: members, 35 | isGuest: is_guest, 36 | fixedMember: fixed_member 37 | } 38 | end 39 | 40 | it { expect(subject).to eq 'id' => '1' } 41 | 42 | context 'fail to request' do 43 | before(:each) do 44 | stub_request( 45 | :post, 46 | 'https://example.cybozu.com/k/v1/template/space.json' 47 | ) 48 | .with(body: request_data.to_json) 49 | .to_return( 50 | body: '{"message":"不正なJSON文字列です。","id":"1505999166-897850006","code":"CB_IJ01"}', 51 | status: 500, 52 | headers: { 'Content-Type' => 'application/json' } 53 | ) 54 | end 55 | 56 | it { expect { subject }.to raise_error Kintone::KintoneError } 57 | end 58 | end 59 | end 60 | -------------------------------------------------------------------------------- /spec/kintone/command/file_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | require 'kintone/command/file' 3 | require 'kintone/api' 4 | 5 | describe Kintone::Command::File do 6 | let(:target) { Kintone::Command::File.new(api) } 7 | let(:api) { Kintone::Api.new('example.cybozu.com', 'Administrator', 'cybozu') } 8 | 9 | describe '#get' do 10 | before(:each) do 11 | stub_request( 12 | :get, 13 | 'https://example.cybozu.com/k/v1/file.json' 14 | ) 15 | .with(body: request_body.to_json) 16 | .to_return(body: attachment, status: 200, headers: { 'Content-type' => 'image/gif' }) 17 | end 18 | 19 | subject { target.get(fileKey) } 20 | 21 | let(:attachment) { Base64.decode64('data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==') } # rubocop:disable Metrics/LineLength 22 | let(:fileKey) { 'file-key-string' } 23 | let(:request_body) { { fileKey: fileKey } } 24 | 25 | it { expect(subject).to eq attachment } 26 | 27 | context 'fail to request' do 28 | before(:each) do 29 | stub_request( 30 | :get, 31 | 'https://example.cybozu.com/k/v1/file.json' 32 | ) 33 | .with(body: request_body.to_json) 34 | .to_return( 35 | body: '{"message":"不正なJSON文字列です。","id":"1505999166-897850006","code":"CB_IJ01"}', 36 | status: 500, 37 | headers: { 'Content-Type' => 'application/json' } 38 | ) 39 | end 40 | 41 | it { expect { subject }.to raise_error Kintone::KintoneError } 42 | end 43 | end 44 | 45 | describe '#register' do 46 | before(:each) do 47 | expect(api) 48 | .to receive(:post_file) 49 | .with(target.instance_variable_get('@url'), path, content_type, original_filename) 50 | .and_return('c15b3870-7505-4ab6-9d8d-b9bdbc74f5d6') 51 | end 52 | 53 | subject { target.register(path, content_type, original_filename) } 54 | 55 | let(:path) { '/path/to/file.txt' } 56 | let(:content_type) { 'text/plain' } 57 | let(:original_filename) { 'fileName.txt' } 58 | 59 | it { is_expected.to eq 'c15b3870-7505-4ab6-9d8d-b9bdbc74f5d6' } 60 | 61 | xcontext 'fail to request' do 62 | # Should consider how to test 63 | end 64 | end 65 | end 66 | -------------------------------------------------------------------------------- /spec/kintone/command/space_thread_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | require 'kintone/command/space_thread' 3 | require 'kintone/api' 4 | 5 | describe Kintone::Command::SpaceThread do 6 | let(:target) { Kintone::Command::SpaceThread.new(api) } 7 | let(:api) { Kintone::Api.new('example.cybozu.com', 'Administrator', 'cybozu') } 8 | 9 | describe '#update' do 10 | before(:each) do 11 | stub_request( 12 | :put, 13 | 'https://example.cybozu.com/k/v1/space/thread.json' 14 | ) 15 | .with(body: request_body) 16 | .to_return( 17 | body: '{}', 18 | status: 200, 19 | headers: { 'Content-type' => 'application/json' } 20 | ) 21 | end 22 | 23 | subject { target.update(id, name: name, body: body) } 24 | 25 | let(:id) { 1 } 26 | 27 | where(:name, :body, :request_body) do 28 | [ 29 | [ 30 | 'example thread', 31 | 'awesome thread!', 32 | '{"id":1,"name":"example thread","body":"awesome thread!"}' 33 | ], 34 | [ 35 | nil, 36 | 'awesome thread!', 37 | '{"id":1,"body":"awesome thread!"}' 38 | ], 39 | [ 40 | 'example thread', 41 | nil, 42 | '{"id":1,"name":"example thread"}' 43 | ], 44 | [ 45 | nil, 46 | nil, 47 | '{"id":1}' 48 | ] 49 | ] 50 | end 51 | 52 | with_them do 53 | it { expect(subject).to be_truthy } 54 | end 55 | 56 | context 'fail to request' do 57 | before(:each) do 58 | stub_request( 59 | :put, 60 | 'https://example.cybozu.com/k/v1/space/thread.json' 61 | ) 62 | .with(body: request_body) 63 | .to_return( 64 | body: '{"message":"不正なJSON文字列です。","id":"1505999166-897850006","code":"CB_IJ01"}', 65 | status: 500, 66 | headers: { 'Content-Type' => 'application/json' } 67 | ) 68 | end 69 | 70 | let(:name) { 'example thread' } 71 | let(:body) { 'awesome thread!' } 72 | let(:request_body) { '{"id":1,"name":"example thread","body":"awesome thread!"}' } 73 | 74 | it { expect { subject }.to raise_error Kintone::KintoneError } 75 | end 76 | end 77 | end 78 | -------------------------------------------------------------------------------- /spec/kintone/command/space_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | require 'kintone/command/space' 3 | require 'kintone/api' 4 | 5 | describe Kintone::Command::Space do 6 | let(:target) { Kintone::Command::Space.new(api) } 7 | let(:api) { Kintone::Api.new('example.cybozu.com', 'Administrator', 'cybozu') } 8 | 9 | describe '#get' do 10 | before(:each) do 11 | stub_request( 12 | :get, 13 | 'https://example.cybozu.com/k/v1/space.json' 14 | ) 15 | .with(body: request_body.to_json) 16 | .to_return( 17 | body: result.to_json, 18 | status: 200, 19 | headers: { 'Content-type' => 'application/json' } 20 | ) 21 | end 22 | 23 | subject { target.get(id) } 24 | 25 | let(:id) { 1 } 26 | let(:request_body) { { id: id } } 27 | let(:result) { { 'id' => '1', 'name' => 'sample space' } } 28 | 29 | it { expect(subject).to eq(result) } 30 | 31 | context 'fail to request' do 32 | before(:each) do 33 | stub_request( 34 | :get, 35 | 'https://example.cybozu.com/k/v1/space.json' 36 | ) 37 | .with(body: request_body.to_json) 38 | .to_return( 39 | body: '{"message":"不正なJSON文字列です。","id":"1505999166-897850006","code":"CB_IJ01"}', 40 | status: 500, 41 | headers: { 'Content-Type' => 'application/json' } 42 | ) 43 | end 44 | 45 | it { expect { subject }.to raise_error Kintone::KintoneError } 46 | end 47 | end 48 | 49 | describe '#delete' do 50 | before(:each) do 51 | stub_request( 52 | :delete, 53 | 'https://example.cybozu.com/k/v1/space.json' 54 | ) 55 | .with(body: { id: 1 }.to_json) 56 | .to_return( 57 | body: '{}', 58 | status: 200, 59 | headers: { 'Content-type' => 'application/json' } 60 | ) 61 | end 62 | 63 | subject { target.delete(id) } 64 | 65 | let(:id) { 1 } 66 | 67 | it { expect(subject).to be_truthy } 68 | 69 | context 'fail to request' do 70 | before(:each) do 71 | stub_request( 72 | :delete, 73 | 'https://example.cybozu.com/k/v1/space.json' 74 | ) 75 | .with(body: { id: 1 }.to_json) 76 | .to_return( 77 | body: '{"message":"不正なJSON文字列です。","id":"1505999166-897850006","code":"CB_IJ01"}', 78 | status: 500, 79 | headers: { 'Content-Type' => 'application/json' } 80 | ) 81 | end 82 | 83 | it { expect { subject }.to raise_error Kintone::KintoneError } 84 | end 85 | end 86 | end 87 | -------------------------------------------------------------------------------- /spec/kintone/command/bulk_request_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | require 'kintone/command/bulk_request' 3 | require 'kintone/api' 4 | 5 | describe Kintone::Command::BulkRequest do 6 | let(:target) { Kintone::Command::BulkRequest.new(api) } 7 | let(:api) { Kintone::Api.new('example.cybozu.com', 'Administrator', 'cybozu') } 8 | 9 | describe '#request' do 10 | before(:each) do 11 | stub_request( 12 | :post, 13 | 'https://example.cybozu.com/k/v1/bulkRequest.json' 14 | ) 15 | .with(body: { requests: requests }.to_json) 16 | .to_return( 17 | body: { 'results' => results }.to_json, 18 | status: 200, 19 | headers: { 'Content-type' => 'application/json' } 20 | ) 21 | end 22 | 23 | subject { target.request(requests) } 24 | 25 | let(:requests) do 26 | [ 27 | { 28 | method: 'POST', 29 | api: '/k/v1/record.json', 30 | payload: { 31 | app: 1972, 32 | record: { 33 | '文字列__1行' => { 34 | value: '文字列__1行を追加します。' 35 | } 36 | } 37 | } 38 | }, 39 | { 40 | method: 'PUT', 41 | api: '/k/v1/record.json', 42 | payload: { 43 | app: 1973, 44 | id: 33, 45 | revision: 2, 46 | record: { 47 | '文字列__1行' => { 48 | value: '文字列__1行を更新します。' 49 | } 50 | } 51 | } 52 | }, 53 | { 54 | method: 'DELETE', 55 | api: '/k/v1/records.json', 56 | payload: { 57 | app: 1974, 58 | ids: [10, 11], 59 | revisions: [1, 1] 60 | } 61 | } 62 | ] 63 | end 64 | 65 | let(:results) do 66 | [ 67 | { 'id' => '39', 'revision' => '1' }, 68 | { 'revision' => '34' }, 69 | {} 70 | ] 71 | end 72 | 73 | it { is_expected.to eq results } 74 | 75 | context 'fail to request' do 76 | before(:each) do 77 | stub_request( 78 | :post, 79 | 'https://example.cybozu.com/k/v1/bulkRequest.json' 80 | ) 81 | .with(body: { requests: requests }.to_json) 82 | .to_return( 83 | body: '{"message":"不正なJSON文字列です。","id":"1505999166-897850006","code":"CB_IJ01"}', 84 | status: 500, 85 | headers: { 'Content-Type' => 'application/json' } 86 | ) 87 | end 88 | 89 | it { expect { subject }.to raise_error Kintone::KintoneError } 90 | end 91 | end 92 | end 93 | -------------------------------------------------------------------------------- /spec/kintone/kintone_error_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | require 'kintone/kintone_error' 3 | 4 | describe Kintone::KintoneError do 5 | let(:target) { Kintone::KintoneError.new(messages, http_status) } 6 | 7 | describe '#message' do 8 | subject { target.message } 9 | 10 | context '不正なJSONの場合' do 11 | let(:messages) do 12 | { 13 | 'message' => '不正なJSON文字列です。', 14 | 'id' => '1505999166-897850006', 15 | 'code' => 'CB_IJ01' 16 | } 17 | end 18 | 19 | let(:http_status) { 500 } 20 | 21 | it { is_expected.to eq '500 [CB_IJ01] 不正なJSON文字列です。(1505999166-897850006)' } 22 | 23 | describe '#message_text' do 24 | subject { target.message_text } 25 | it { is_expected.to eq '不正なJSON文字列です。' } 26 | end 27 | 28 | describe '#id' do 29 | subject { target.id } 30 | it { is_expected.to eq '1505999166-897850006' } 31 | end 32 | 33 | describe '#code' do 34 | subject { target.code } 35 | it { is_expected.to eq 'CB_IJ01' } 36 | end 37 | 38 | describe '#http_status' do 39 | subject { target.http_status } 40 | it { is_expected.to eq 500 } 41 | end 42 | 43 | describe '#errors' do 44 | subject { target.errors } 45 | it { is_expected.to be_nil } 46 | end 47 | end 48 | 49 | context 'Validation Errorの場合' do 50 | let(:messages) do 51 | { 52 | 'message' => '入力内容が正しくありません。', 53 | 'id' => '1505999166-836316825', 54 | 'code' => 'CB_VA01', 55 | 'errors' => { 56 | 'record.field_code.value' => { 57 | 'messages' => ['必須です。'] 58 | } 59 | } 60 | } 61 | end 62 | 63 | let(:http_status) { 400 } 64 | 65 | it { is_expected.to eq '400 [CB_VA01] 入力内容が正しくありません。(1505999166-836316825)' } 66 | 67 | describe '#message_text' do 68 | subject { target.message_text } 69 | it { is_expected.to eq '入力内容が正しくありません。' } 70 | end 71 | 72 | describe '#id' do 73 | subject { target.id } 74 | it { is_expected.to eq '1505999166-836316825' } 75 | end 76 | 77 | describe '#code' do 78 | subject { target.code } 79 | it { is_expected.to eq 'CB_VA01' } 80 | end 81 | 82 | describe '#http_status' do 83 | subject { target.http_status } 84 | it { is_expected.to eq 400 } 85 | end 86 | 87 | describe '#errors' do 88 | subject { target.errors['record.field_code.value']['messages'].first } 89 | it { is_expected.to eq '必須です。' } 90 | end 91 | end 92 | end 93 | end 94 | -------------------------------------------------------------------------------- /spec/kintone/command/apps_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | require 'kintone/command/apps' 3 | 4 | describe Kintone::Command::Apps do 5 | let(:target) { Kintone::Command::Apps.new(api) } 6 | let(:api) { Kintone::Api.new('example.cybozu.com', 'Administrator', 'cybozu') } 7 | 8 | describe '#get' do 9 | subject { target.get(params) } 10 | 11 | context '引数にHashのデータを指定した場合' do 12 | before(:each) do 13 | stub_request( 14 | :get, 15 | 'https://example.cybozu.com/k/v1/apps.json' 16 | ) 17 | .with(body: params.to_json) 18 | .to_return( 19 | body: { apps: [] }.to_json, 20 | status: 200, 21 | headers: { 'Content-type' => 'application/json' } 22 | ) 23 | end 24 | 25 | where(:params) do 26 | [ 27 | [{ ids: [100, 200] }], 28 | [{ ids: [] }], 29 | [{ ids: nil }], 30 | [{ codes: ['AAA', 'BBB'] }], 31 | [{ codes: [] }], 32 | [{ codes: nil }], 33 | [{ name: '名前' }], 34 | [{ name: '' }], 35 | [{ name: nil }], 36 | [{ spaceIds: [100, 200] }], 37 | [{ spaceIds: [] }], 38 | [{ spaceIds: nil }], 39 | [{ limit: 100 }], 40 | [{ limit: nil }], 41 | [{ offset: 100 }], 42 | [{ offset: nil }], 43 | [{}] 44 | ] 45 | end 46 | 47 | with_them do 48 | it { is_expected.to be_a_kind_of(Array) } 49 | end 50 | end 51 | 52 | context '引数にnilを指定した場合' do 53 | let(:params) { nil } 54 | 55 | before(:each) do 56 | stub_request( 57 | :get, 58 | 'https://example.cybozu.com/k/v1/apps.json' 59 | ) 60 | .with(body: params.to_h.to_json) 61 | .to_return( 62 | body: { apps: [] }.to_json, 63 | status: 200, 64 | headers: { 'Content-type' => 'application/json' } 65 | ) 66 | end 67 | 68 | it { is_expected.to be_a_kind_of(Array) } 69 | end 70 | 71 | context 'fail to request' do 72 | before(:each) do 73 | stub_request( 74 | :get, 75 | 'https://example.cybozu.com/k/v1/apps.json' 76 | ) 77 | .with(body: params.to_json) 78 | .to_return( 79 | body: '{"message":"不正なJSON文字列です。","id":"1505999166-897850006","code":"CB_IJ01"}', 80 | status: 500, 81 | headers: { 'Content-Type' => 'application/json' } 82 | ) 83 | end 84 | 85 | let(:params) { { ids: [100, 200] } } 86 | 87 | it { expect { subject }.to raise_error Kintone::KintoneError } 88 | end 89 | end 90 | end 91 | -------------------------------------------------------------------------------- /lib/kintone/command/accessor.rb: -------------------------------------------------------------------------------- 1 | class Kintone::Command 2 | # common 3 | autoload :Record, 'kintone/command/record' 4 | autoload :Records, 'kintone/command/records' 5 | autoload :BulkRequest, 'kintone/command/bulk_request' 6 | autoload :Form, 'kintone/command/form' 7 | autoload :PreviewForm, 'kintone/command/preview_form' 8 | autoload :App, 'kintone/command/app' 9 | autoload :Apps, 'kintone/command/apps' 10 | autoload :AppAcl, 'kintone/command/app_acl' 11 | autoload :RecordAcl, 'kintone/command/record_acl' 12 | autoload :FieldAcl, 'kintone/command/field_acl' 13 | autoload :Space, 'kintone/command/space' 14 | autoload :SpaceBody, 'kintone/command/space_body' 15 | autoload :SpaceThread, 'kintone/command/space_thread' 16 | autoload :SpaceMembers, 'kintone/command/space_members' 17 | autoload :File, 'kintone/command/file' 18 | 19 | # other than guest 20 | autoload :TemplateSpace, 'kintone/command/template_space' 21 | autoload :Guests, 'kintone/command/guests' 22 | autoload :Apis, 'kintone/command/apis' 23 | 24 | # guest only 25 | autoload :SpaceGuests, 'kintone/command/space_guests' 26 | 27 | module Accessor 28 | # common 29 | def record(api) 30 | Record.new(api) 31 | end 32 | 33 | def records(api) 34 | Records.new(api) 35 | end 36 | 37 | def bulk_request(api) 38 | BulkRequest.new(api) 39 | end 40 | 41 | def form(api) 42 | Form.new(api) 43 | end 44 | 45 | def preview_form(api) 46 | PreviewForm.new(api) 47 | end 48 | 49 | def app(api) 50 | App.new(api) 51 | end 52 | 53 | def apps(api) 54 | Apps.new(api) 55 | end 56 | 57 | def app_acl(api) 58 | AppAcl.new(api) 59 | end 60 | 61 | def record_acl(api) 62 | RecordAcl.new(api) 63 | end 64 | 65 | def field_acl(api) 66 | FieldAcl.new(api) 67 | end 68 | 69 | def space(api) 70 | Space.new(api) 71 | end 72 | 73 | def space_body(api) 74 | SpaceBody.new(api) 75 | end 76 | 77 | def space_thread(api) 78 | SpaceThread.new(api) 79 | end 80 | 81 | def space_members(api) 82 | SpaceMembers.new(api) 83 | end 84 | 85 | def file(api) 86 | File.new(api) 87 | end 88 | 89 | # other than guest 90 | def template_space(api) 91 | TemplateSpace.new(api) 92 | end 93 | 94 | def guests(api) 95 | Guests.new(api) 96 | end 97 | 98 | def apis(api) 99 | Apis.new(api) 100 | end 101 | 102 | # guest only 103 | def space_guests(api) 104 | SpaceGuests.new(api) 105 | end 106 | 107 | alias bulk bulk_request 108 | end 109 | end 110 | -------------------------------------------------------------------------------- /lib/kintone/query.rb: -------------------------------------------------------------------------------- 1 | require 'kintone/query/extension' 2 | 3 | class Kintone::Query 4 | def initialize(&block) 5 | @query = [] 6 | instance_eval(&block) if block_given? 7 | end 8 | 9 | def field(code) 10 | condition = Field.new(code) 11 | @query << condition 12 | condition 13 | end 14 | 15 | def and! 16 | @query << 'and' 17 | end 18 | 19 | def or! 20 | @query << 'or' 21 | end 22 | 23 | def precede(&block) 24 | @query << "(#{Kintone::Query.new(&block)})" if block_given? 25 | end 26 | 27 | def login_user 28 | function_string('LOGINUSER()') 29 | end 30 | 31 | def primary_organization 32 | function_string('PRIMARY_ORGANIZATION()') 33 | end 34 | 35 | def now 36 | function_string('NOW()') 37 | end 38 | 39 | def today 40 | function_string('TODAY()') 41 | end 42 | 43 | def this_month 44 | function_string('THIS_MONTH()') 45 | end 46 | 47 | def last_month 48 | function_string('LAST_MONTH()') 49 | end 50 | 51 | def this_year 52 | function_string('THIS_YEAR()') 53 | end 54 | 55 | def order_by(field, sort = :asc) 56 | @query << "order by #{field} #{sort}" 57 | end 58 | 59 | def limit(count) 60 | @query << "limit #{count}" 61 | end 62 | 63 | def offset(index) 64 | @query << "offset #{index}" 65 | end 66 | 67 | def to_s 68 | @query.map(&:to_s).join(' ') 69 | end 70 | 71 | def inspect 72 | to_s 73 | end 74 | 75 | alias f field 76 | 77 | private 78 | 79 | def function_string(function) 80 | function.instance_eval do 81 | class << self 82 | define_method :query_format, proc { self } 83 | end 84 | end 85 | function 86 | end 87 | 88 | class Field 89 | using Kintone::Query::Extention 90 | 91 | def initialize(code) 92 | @code = code.to_s 93 | end 94 | 95 | def ==(other) 96 | save('=', other.query_format) 97 | end 98 | 99 | def !=(other) 100 | save('!=', other.query_format) 101 | end 102 | 103 | def >(other) 104 | save('>', other.query_format) 105 | end 106 | 107 | def <(other) 108 | save('<', other.query_format) 109 | end 110 | 111 | def >=(other) 112 | save('>=', other.query_format) 113 | end 114 | 115 | def <=(other) 116 | save('<=', other.query_format) 117 | end 118 | 119 | def in(other) 120 | other = "(#{other.map { |v| v.query_format }.join(', ')})" if other.is_a?(Array) 121 | save('in', other) 122 | end 123 | 124 | def not_in(other) 125 | other = "(#{other.map { |v| v.query_format }.join(', ')})" if other.is_a?(Array) 126 | save('not in', other) 127 | end 128 | 129 | def like(other) 130 | save('like', other.query_format) 131 | end 132 | 133 | def not_like(other) 134 | save('not like', other.query_format) 135 | end 136 | 137 | def to_s 138 | "#{@code} #{@condition} #{@other}" 139 | end 140 | 141 | def inspect 142 | to_s 143 | end 144 | 145 | private 146 | 147 | def save(condition, other) 148 | @condition ||= condition 149 | @other ||= other 150 | end 151 | end 152 | end 153 | -------------------------------------------------------------------------------- /spec/kintone/command/guests_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | require 'kintone/command/guests' 3 | require 'kintone/api' 4 | 5 | describe Kintone::Command::Guests do 6 | let(:target) { Kintone::Command::Guests.new(api) } 7 | let(:api) { Kintone::Api.new('example.cybozu.com', 'Administrator', 'cybozu') } 8 | 9 | describe '#register' do 10 | before(:each) do 11 | stub_request( 12 | :post, 13 | 'https://example.cybozu.com/k/v1/guests.json' 14 | ) 15 | .with(body: { guests: guests }.to_json) 16 | .to_return( 17 | body: '{}', 18 | status: 200, 19 | headers: { 'Content-type' => 'application/json' } 20 | ) 21 | end 22 | 23 | subject { target.register(guests) } 24 | 25 | let(:guests) do 26 | [ 27 | { 28 | code: 'hoge@example.com', 29 | password: 'password', 30 | timezone: 'Asia/Tokyo', 31 | locale: 'ja', 32 | image: '78a586f2-e73e-4a70-bec2-43976a60746e', 33 | name: '東京 三郎', 34 | surNameReading: 'とうきょう', 35 | givenNameReading: 'さぶろう', 36 | company: 'サイボウズ株式会社', 37 | division: '営業部', 38 | phone: '999-456-7890', 39 | callto: 'tokyo3rou' 40 | } 41 | ] 42 | end 43 | 44 | it { is_expected.to be_truthy } 45 | 46 | context 'fail to request' do 47 | before(:each) do 48 | stub_request( 49 | :post, 50 | 'https://example.cybozu.com/k/v1/guests.json' 51 | ) 52 | .with(body: { guests: guests }.to_json) 53 | .to_return( 54 | body: '{"message":"不正なJSON文字列です。","id":"1505999166-897850006","code":"CB_IJ01"}', 55 | status: 500, 56 | headers: { 'Content-type' => 'application/json' } 57 | ) 58 | end 59 | 60 | it { expect { subject }.to raise_error Kintone::KintoneError } 61 | end 62 | end 63 | 64 | describe '#delete' do 65 | before(:each) do 66 | stub_request( 67 | :delete, 68 | 'https://example.cybozu.com/k/v1/guests.json' 69 | ) 70 | .with(body: { guests: guests }.to_json) 71 | .to_return( 72 | body: '{}', 73 | status: 200, 74 | headers: { 'Content-type' => 'application/json' } 75 | ) 76 | end 77 | 78 | subject { target.delete(guests) } 79 | 80 | let(:guests) do 81 | [ 82 | 'guest1@example.com', 83 | 'guest2@example.com', 84 | 'guest3@example.com' 85 | ] 86 | end 87 | 88 | it { is_expected.to be_truthy } 89 | 90 | context 'fail to request' do 91 | before(:each) do 92 | stub_request( 93 | :delete, 94 | 'https://example.cybozu.com/k/v1/guests.json' 95 | ) 96 | .with(body: { guests: guests }.to_json) 97 | .to_return( 98 | body: '{"message":"不正なJSON文字列です。","id":"1505999166-897850006","code":"CB_IJ01"}', 99 | status: 500, 100 | headers: { 'Content-Type' => 'application/json' } 101 | ) 102 | end 103 | 104 | it { expect { subject }.to raise_error Kintone::KintoneError } 105 | end 106 | end 107 | end 108 | -------------------------------------------------------------------------------- /spec/kintone/command/space_members_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | require 'kintone/command/space_members' 3 | require 'kintone/api' 4 | 5 | describe Kintone::Command::SpaceMembers do 6 | let(:target) { Kintone::Command::SpaceMembers.new(api) } 7 | let(:api) { Kintone::Api.new('example.cybozu.com', 'Administrator', 'cybozu') } 8 | 9 | describe '#get' do 10 | before(:each) do 11 | stub_request( 12 | :get, 13 | 'https://example.cybozu.com/k/v1/space/members.json' 14 | ) 15 | .with(body: request_body.to_json) 16 | .to_return( 17 | body: response_data.to_json, 18 | status: 200, 19 | headers: { 'Content-type' => 'application/json' } 20 | ) 21 | end 22 | 23 | subject { target.get(id) } 24 | 25 | let(:id) { 1 } 26 | let(:request_body) { { id: id } } 27 | let(:response_data) { { 'members' => members } } 28 | let(:members) do 29 | [ 30 | { 31 | 'entity' => { 'type' => 'USER', 'code' => 'user1' }, 32 | 'isAdmin' => false, 33 | 'isImplicit' => true 34 | } 35 | ] 36 | end 37 | 38 | it { expect(subject).to match members } 39 | 40 | context 'fail to request' do 41 | before(:each) do 42 | stub_request( 43 | :get, 44 | 'https://example.cybozu.com/k/v1/space/members.json' 45 | ) 46 | .with(body: request_body.to_json) 47 | .to_return( 48 | body: '{"message":"不正なJSON文字列です。","id":"1505999166-897850006","code":"CB_IJ01"}', 49 | status: 500, 50 | headers: { 'Content-Type' => 'application/json' } 51 | ) 52 | end 53 | 54 | it { expect { subject }.to raise_error Kintone::KintoneError } 55 | end 56 | end 57 | 58 | describe '#update' do 59 | before(:each) do 60 | stub_request( 61 | :put, 62 | 'https://example.cybozu.com/k/v1/space/members.json' 63 | ) 64 | .with(body: request_data.to_json) 65 | .to_return( 66 | body: '{}', 67 | status: 200, 68 | headers: { 'Content-type' => 'application/json' } 69 | ) 70 | end 71 | 72 | subject { target.update(id, members) } 73 | 74 | let(:id) { 1 } 75 | let(:members) do 76 | [ 77 | { 78 | 'entity' => { 'type' => 'USER', 'code' => 'user1' }, 79 | 'isAdmin' => false, 80 | 'isImplicit' => true 81 | } 82 | ] 83 | end 84 | 85 | let(:request_data) do 86 | { 87 | 'id' => 1, 88 | 'members' => [ 89 | { 90 | 'entity' => { 'type' => 'USER', 'code' => 'user1' }, 91 | 'isAdmin' => false, 92 | 'isImplicit' => true 93 | } 94 | ] 95 | } 96 | end 97 | 98 | it { expect(subject).to be_truthy } 99 | 100 | context 'fail to request' do 101 | before(:each) do 102 | stub_request( 103 | :put, 104 | 'https://example.cybozu.com/k/v1/space/members.json' 105 | ) 106 | .with(body: request_data.to_json) 107 | .to_return( 108 | body: '{"message":"不正なJSON文字列です。","id":"1505999166-897850006","code":"CB_IJ01"}', 109 | status: 500, 110 | headers: { 'Content-Type' => 'application/json' } 111 | ) 112 | end 113 | 114 | it { expect { subject }.to raise_error Kintone::KintoneError } 115 | end 116 | end 117 | end 118 | -------------------------------------------------------------------------------- /lib/kintone/api.rb: -------------------------------------------------------------------------------- 1 | require 'faraday' 2 | require 'faraday_middleware' 3 | require 'base64' 4 | require 'json' 5 | require 'kintone/command/accessor' 6 | require 'kintone/api/guest' 7 | require 'kintone/query' 8 | require 'kintone/kintone_error' 9 | 10 | class Kintone::Api 11 | BASE_PATH = '/k/v1/'.freeze 12 | COMMAND = '%s.json'.freeze 13 | ACCESSIBLE_COMMAND = [ 14 | :record, :records, :form, :app_acl, :record_acl, 15 | :field_acl, :template_space, :space, :space_body, :space_thread, 16 | :space_members, :guests, :app, :apps, :apis, 17 | :bulk_request, :bulk, :file, :preview_form 18 | ].freeze 19 | 20 | def initialize(domain, user, password = nil) 21 | @connection = 22 | Faraday.new(url: "https://#{domain}", headers: build_headers(user, password)) do |builder| 23 | builder.request :url_encoded 24 | builder.request :multipart 25 | builder.response :json, content_type: /\bjson$/ 26 | builder.adapter :net_http 27 | end 28 | 29 | yield(@connection) if block_given? 30 | end 31 | 32 | def get_url(command) 33 | BASE_PATH + (COMMAND % command) 34 | end 35 | 36 | def guest(space_id) 37 | Kintone::Api::Guest.new(space_id, self) 38 | end 39 | 40 | def get(url, params = {}) 41 | response = 42 | @connection.get do |request| 43 | request.url url 44 | # NOTE: Request URI Too Large 対策 45 | request.headers['Content-Type'] = 'application/json' 46 | request.body = params.to_h.to_json 47 | end 48 | raise Kintone::KintoneError.new(response.body, response.status) if response.status != 200 49 | response.body 50 | end 51 | 52 | def post(url, body) 53 | response = 54 | @connection.post do |request| 55 | request.url url 56 | request.headers['Content-Type'] = 'application/json' 57 | request.body = body.to_json 58 | end 59 | raise Kintone::KintoneError.new(response.body, response.status) if response.status != 200 60 | response.body 61 | end 62 | 63 | def put(url, body) 64 | response = 65 | @connection.put do |request| 66 | request.url url 67 | request.headers['Content-Type'] = 'application/json' 68 | request.body = body.to_json 69 | end 70 | raise Kintone::KintoneError.new(response.body, response.status) if response.status != 200 71 | response.body 72 | end 73 | 74 | def delete(url, body = nil) 75 | response = 76 | @connection.delete do |request| 77 | request.url url 78 | request.headers['Content-Type'] = 'application/json' 79 | request.body = body.to_json 80 | end 81 | raise Kintone::KintoneError.new(response.body, response.status) if response.status != 200 82 | response.body 83 | end 84 | 85 | def post_file(url, path, content_type, original_filename) 86 | response = 87 | @connection.post do |request| 88 | request.url url 89 | request.headers['Content-Type'] = 'multipart/form-data' 90 | request.body = { file: Faraday::UploadIO.new(path, content_type, original_filename) } 91 | end 92 | raise Kintone::KintoneError.new(response.body, response.status) if response.status != 200 93 | response.body['fileKey'] 94 | end 95 | 96 | def method_missing(name, *args) 97 | if ACCESSIBLE_COMMAND.include?(name) 98 | CommandAccessor.send(name, self) 99 | else 100 | super 101 | end 102 | end 103 | 104 | def respond_to_missing?(name, *args) 105 | ACCESSIBLE_COMMAND.include?(name) || super 106 | end 107 | 108 | class CommandAccessor 109 | extend Kintone::Command::Accessor 110 | end 111 | 112 | private 113 | 114 | def build_headers(user, password) 115 | if password # パスワード認証 116 | { 'X-Cybozu-Authorization' => Base64.strict_encode64("#{user}:#{password}") } 117 | else # APIトークン認証 118 | { 'X-Cybozu-API-Token' => user } 119 | end 120 | end 121 | end 122 | -------------------------------------------------------------------------------- /spec/kintone/command/apis_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | require 'kintone/command/apis' 3 | 4 | describe Kintone::Command::Apis do 5 | let(:target) { Kintone::Command::Apis.new(api) } 6 | let(:api) { Kintone::Api.new('example.cybozu.com', 'Administrator', 'cybozu') } 7 | 8 | describe '#get' do 9 | before(:each) do 10 | stub_request( 11 | :get, 12 | 'https://example.cybozu.com/k/v1/apis.json' 13 | ) 14 | .to_return( 15 | body: response_data.to_json, 16 | status: 200, 17 | headers: { 'Content-type' => 'application/json' } 18 | ) 19 | end 20 | 21 | subject { target.get } 22 | 23 | def response_data 24 | { 25 | 'baseUrl' => 'https://example.cybozu.com/k/v1/', 26 | 'apis' => { 27 | 'records/get' => { 28 | 'link' => 'apis/records/get.json' 29 | } 30 | } 31 | } 32 | end 33 | 34 | it { is_expected.to eq(response_data) } 35 | 36 | context 'fail to request' do 37 | before(:each) do 38 | stub_request( 39 | :get, 40 | 'https://example.cybozu.com/k/v1/apis.json' 41 | ) 42 | .to_return( 43 | body: '{"message":"不正なJSON文字列です。","id":"1505999166-897850006","code":"CB_IJ01"}', 44 | status: 500, 45 | headers: { 'Content-Type' => 'application/json' } 46 | ) 47 | end 48 | 49 | it { expect { subject }.to raise_error Kintone::KintoneError } 50 | end 51 | end 52 | 53 | describe '#get_details_of' do 54 | before(:each) do 55 | stub_request( 56 | :get, 57 | 'https://example.cybozu.com/k/v1/apis/records/get.json' 58 | ) 59 | .to_return( 60 | body: response_data.to_json, 61 | status: 200, 62 | headers: { 'Content-type' => 'application/json' } 63 | ) 64 | end 65 | 66 | subject { target.get_details_of(link) } 67 | 68 | let(:link) { 'apis/records/get.json' } 69 | 70 | def response_data 71 | { 72 | 'id' => 'GetRecords', 73 | 'baseUrl' => 'https://example.cybozu.com/k/v1/', 74 | 'path' => 'records.json', 75 | 'httpMethod' => 'GET' 76 | } 77 | end 78 | 79 | it { is_expected.to eq(response_data) } 80 | 81 | context 'fail to request' do 82 | before(:each) do 83 | stub_request( 84 | :get, 85 | 'https://example.cybozu.com/k/v1/apis/records/get.json' 86 | ) 87 | .to_return( 88 | body: '{"message":"不正なJSON文字列です。","id":"1505999166-897850006","code":"CB_IJ01"}', 89 | status: 500, 90 | headers: { 'Content-Type' => 'application/json' } 91 | ) 92 | end 93 | 94 | it { expect { subject }.to raise_error Kintone::KintoneError } 95 | end 96 | end 97 | 98 | describe '#get_details_of_key' do 99 | before(:each) do 100 | stub_request( 101 | :get, 102 | 'https://example.cybozu.com/k/v1/apis.json' 103 | ) 104 | .to_return( 105 | body: apis_response_data.to_json, 106 | status: 200, 107 | headers: { 'Content-type' => 'application/json' } 108 | ) 109 | 110 | stub_request( 111 | :get, 112 | 'https://example.cybozu.com/k/v1/apis/records/get.json' 113 | ) 114 | .to_return( 115 | body: api_response_data.to_json, 116 | status: 200, 117 | headers: { 'Content-type' => 'application/json' } 118 | ) 119 | end 120 | 121 | subject { target.get_details_of_key(key) } 122 | 123 | def apis_response_data 124 | { 125 | 'baseUrl' => 'https://example.cybozu.com/k/v1/', 126 | 'apis' => { 127 | 'records/get' => { 128 | 'link' => 'apis/records/get.json' 129 | } 130 | } 131 | } 132 | end 133 | 134 | def api_response_data 135 | { 136 | 'id' => 'GetRecords', 137 | 'baseUrl' => 'https://example.cybozu.com/k/v1/', 138 | 'path' => 'records.json', 139 | 'httpMethod' => 'GET' 140 | } 141 | end 142 | 143 | context 'with key that exists' do 144 | let(:key) { 'records/get' } 145 | 146 | it { is_expected.to eq(api_response_data) } 147 | end 148 | 149 | context 'with key that does not exists' do 150 | let(:key) { 'records/hoge' } 151 | 152 | it { expect { subject }.to raise_error NoMethodError } 153 | end 154 | 155 | context 'with nil' do 156 | let(:key) { nil } 157 | 158 | it { expect { subject }.to raise_error NoMethodError } 159 | end 160 | 161 | context 'fail to request' do 162 | before(:each) do 163 | stub_request( 164 | :get, 165 | 'https://example.cybozu.com/k/v1/apis/records/get.json' 166 | ) 167 | .to_return( 168 | body: '{"message":"不正なJSON文字列です。","id":"1505999166-897850006","code":"CB_IJ01"}', 169 | status: 500, 170 | headers: { 'Content-Type' => 'application/json' } 171 | ) 172 | end 173 | 174 | let(:key) { 'records/get' } 175 | 176 | it { expect { subject }.to raise_error Kintone::KintoneError } 177 | end 178 | end 179 | end 180 | -------------------------------------------------------------------------------- /spec/kintone/command/record_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | require 'kintone/command/record' 3 | require 'kintone/api' 4 | require 'kintone/type/record' 5 | 6 | describe Kintone::Command::Record do 7 | let(:target) { Kintone::Command::Record.new(api) } 8 | let(:api) { Kintone::Api.new('www.example.com', 'Administrator', 'cybozu') } 9 | 10 | describe '#get' do 11 | before(:each) do 12 | stub_request(:get, 'https://www.example.com/k/v1/record.json') 13 | .with(body: request_body.to_json) 14 | .to_return( 15 | body: '{"result":"ok"}', 16 | status: 200, 17 | headers: { 'Content-Type' => 'application/json' } 18 | ) 19 | end 20 | 21 | subject { target.get(app, id) } 22 | 23 | let(:request_body) { { app: app, id: id } } 24 | 25 | where(:app, :id) do 26 | [ 27 | [8, 100], 28 | ['8', '100'] 29 | ] 30 | end 31 | 32 | with_them do 33 | it { expect(subject).to eq 'result' => 'ok' } 34 | end 35 | 36 | context 'fail to request' do 37 | before(:each) do 38 | stub_request(:get, 'https://www.example.com/k/v1/record.json') 39 | .with(body: request_body) 40 | .to_return( 41 | body: '{"message":"不正なJSON文字列です。","id":"1505999166-897850006","code":"CB_IJ01"}', 42 | status: 500, 43 | headers: { 'Content-Type' => 'application/json' } 44 | ) 45 | end 46 | 47 | let(:app) { 8 } 48 | let(:id) { 100 } 49 | 50 | it { expect { subject }.to raise_error Kintone::KintoneError } 51 | end 52 | end 53 | 54 | describe '#register' do 55 | before(:each) do 56 | stub_request( 57 | :post, 58 | 'https://www.example.com/k/v1/record.json' 59 | ) 60 | .with(body: request_body.to_json) 61 | .to_return( 62 | body: response_body.to_json, 63 | status: 200, 64 | headers: { 'Content-type' => 'application/json' } 65 | ) 66 | end 67 | 68 | subject { target.register(app, record) } 69 | 70 | let(:app) { 7 } 71 | let(:request_body) do 72 | { 73 | 'app' => 7, 74 | 'record' => { 75 | 'number' => { 'value' => '123456' }, 76 | 'rich_editor' => { 'value' => 'testtest' }, 77 | 'user_select' => { 'value' => [{ 'code' => 'sato' }] } 78 | } 79 | } 80 | end 81 | let(:response_body) { { 'id' => '100', 'revision' => '1' } } 82 | 83 | context 'use hash' do 84 | let(:record) do 85 | { 86 | 'number' => { 'value' => '123456' }, 87 | 'rich_editor' => { 'value' => 'testtest' }, 88 | 'user_select' => { 'value' => [{ 'code' => 'sato' }] } 89 | } 90 | end 91 | 92 | it { expect(subject).to eq response_body } 93 | end 94 | 95 | context 'use record' do 96 | let(:record) do 97 | Kintone::Type::Record.new( 98 | number: '123456', 99 | rich_editor: 'testtest', 100 | user_select: [{ 'code' => 'sato' }] 101 | ) 102 | end 103 | 104 | it { expect(subject).to eq response_body } 105 | end 106 | 107 | context 'fail to request' do 108 | before(:each) do 109 | stub_request( 110 | :post, 111 | 'https://www.example.com/k/v1/record.json' 112 | ) 113 | .with(body: request_body.to_json) 114 | .to_return( 115 | body: '{"message":"不正なJSON文字列です。","id":"1505999166-897850006","code":"CB_IJ01"}', 116 | status: 500, 117 | headers: { 'Content-Type' => 'application/json' } 118 | ) 119 | end 120 | 121 | let(:record) do 122 | { 123 | 'number' => { 'value' => '123456' }, 124 | 'rich_editor' => { 'value' => 'testtest' }, 125 | 'user_select' => { 'value' => [{ 'code' => 'sato' }] } 126 | } 127 | end 128 | 129 | it { expect { subject }.to raise_error Kintone::KintoneError } 130 | end 131 | end 132 | 133 | describe '#update' do 134 | before(:each) do 135 | stub_request( 136 | :put, 137 | 'https://www.example.com/k/v1/record.json' 138 | ) 139 | .with(body: request_body.to_json) 140 | .to_return( 141 | body: response_body.to_json, 142 | status: 200, 143 | headers: { 'Content-type' => 'application/json' } 144 | ) 145 | end 146 | 147 | subject { target.update(app, id, record) } 148 | 149 | let(:app) { 4 } 150 | let(:id) { 1 } 151 | let(:hash_record) { { 'string_multi' => { 'value' => 'character string is changed' } } } 152 | let(:record_record) { Kintone::Type::Record.new(string_multi: 'character string is changed') } 153 | let(:response_body) { { revision: '2' } } 154 | 155 | context 'without revision' do 156 | let(:request_body) { { 'app' => 4, 'id' => 1, 'record' => hash_record } } 157 | 158 | context 'use hash' do 159 | let(:record) { hash_record } 160 | 161 | it { expect(subject).to match 'revision' => '2' } 162 | end 163 | 164 | context 'use record' do 165 | let(:record) { record_record } 166 | 167 | it { expect(subject).to match 'revision' => '2' } 168 | end 169 | end 170 | 171 | context 'with revision' do 172 | subject { target.update(app, id, record, revision: revision) } 173 | 174 | let(:revision) { 1 } 175 | let(:request_body) { { 'app' => 4, 'id' => 1, 'record' => hash_record, 'revision' => 1 } } 176 | 177 | context 'use hash' do 178 | let(:record) { hash_record } 179 | 180 | it { expect(subject).to match 'revision' => '2' } 181 | end 182 | 183 | context 'use record' do 184 | let(:record) { record_record } 185 | 186 | it { expect(subject).to match 'revision' => '2' } 187 | end 188 | end 189 | 190 | context 'fail to request' do 191 | before(:each) do 192 | stub_request( 193 | :put, 194 | 'https://www.example.com/k/v1/record.json' 195 | ) 196 | .with(body: request_body.to_json) 197 | .to_return( 198 | body: '{"message":"不正なJSON文字列です。","id":"1505999166-897850006","code":"CB_IJ01"}', 199 | status: 500, 200 | headers: { 'Content-Type' => 'application/json' } 201 | ) 202 | end 203 | 204 | let(:request_body) { { 'app' => 4, 'id' => 1, 'record' => hash_record } } 205 | let(:record) { hash_record } 206 | 207 | it { expect { subject }.to raise_error Kintone::KintoneError } 208 | end 209 | end 210 | end 211 | -------------------------------------------------------------------------------- /spec/kintone/api/guest_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | require 'kintone/api/guest' 3 | require 'kintone/api' 4 | 5 | describe Kintone::Api::Guest do 6 | let(:target) { Kintone::Api::Guest.new(space, api) } 7 | let(:space) { 1 } 8 | let(:api) { Kintone::Api.new('example.cybozu.com', 'Administrator', 'cybozu') } 9 | 10 | describe '#get_url' do 11 | subject { target.get_url(command) } 12 | 13 | let(:command) { 'path' } 14 | 15 | it { expect(subject).to eq('/k/guest/1/v1/path.json') } 16 | end 17 | 18 | describe '#get' do 19 | before(:each) do 20 | stub_request( 21 | :get, 22 | 'https://example.cybozu.com/k/guest/1/v1/path.json' 23 | ) 24 | .with( 25 | headers: { 'X-Cybozu-Authorization' => 'QWRtaW5pc3RyYXRvcjpjeWJvenU=' }, 26 | body: params.to_json 27 | ) 28 | .to_return( 29 | body: '{"abc":"def"}', 30 | status: 200, 31 | headers: { 'Content-type' => 'application/json' } 32 | ) 33 | end 34 | 35 | subject { target.get(path, params) } 36 | 37 | let(:path) { '/k/guest/1/v1/path.json' } 38 | let(:params) { { p1: 'abc', p2: 'def' } } 39 | 40 | it { expect(subject).to eq 'abc' => 'def' } 41 | 42 | context 'fail to request' do 43 | before(:each) do 44 | stub_request( 45 | :get, 46 | 'https://example.cybozu.com/k/guest/1/v1/path.json' 47 | ) 48 | .with( 49 | headers: { 'X-Cybozu-Authorization' => 'QWRtaW5pc3RyYXRvcjpjeWJvenU=' }, 50 | body: params.to_json 51 | ) 52 | .to_return( 53 | body: '{"message":"不正なJSON文字列です。","id":"1505999166-897850006","code":"CB_IJ01"}', 54 | status: 500 55 | ) 56 | end 57 | 58 | it { expect { subject }.to raise_error Kintone::KintoneError } 59 | end 60 | end 61 | 62 | describe '#post' do 63 | before(:each) do 64 | stub_request( 65 | :post, 66 | 'https://example.cybozu.com/k/guest/1/v1/path.json' 67 | ) 68 | .with( 69 | headers: { 'X-Cybozu-Authorization' => 'QWRtaW5pc3RyYXRvcjpjeWJvenU=' }, 70 | body: '{"p1":"abc","p2":"def"}' 71 | ) 72 | .to_return( 73 | body: '{"abc":"def"}', 74 | status: 200, 75 | headers: { 'Content-type' => 'application/json' } 76 | ) 77 | end 78 | 79 | subject { target.post(path, body) } 80 | 81 | let(:path) { '/k/guest/1/v1/path.json' } 82 | let(:body) { { 'p1' => 'abc', 'p2' => 'def' } } 83 | 84 | it { expect(subject).to eq 'abc' => 'def' } 85 | 86 | context 'fail to request' do 87 | before(:each) do 88 | stub_request( 89 | :post, 90 | 'https://example.cybozu.com/k/guest/1/v1/path.json' 91 | ) 92 | .with( 93 | headers: { 'X-Cybozu-Authorization' => 'QWRtaW5pc3RyYXRvcjpjeWJvenU=' }, 94 | body: '{"p1":"abc","p2":"def"}' 95 | ) 96 | .to_return( 97 | body: '{"message":"不正なJSON文字列です。","id":"1505999166-897850006","code":"CB_IJ01"}', 98 | status: 500 99 | ) 100 | end 101 | 102 | it { expect { subject }.to raise_error Kintone::KintoneError } 103 | end 104 | end 105 | 106 | describe '#put' do 107 | before(:each) do 108 | stub_request( 109 | :put, 110 | 'https://example.cybozu.com/k/guest/1/v1/path.json' 111 | ) 112 | .with( 113 | headers: { 'X-Cybozu-Authorization' => 'QWRtaW5pc3RyYXRvcjpjeWJvenU=' }, 114 | body: '{"p1":"abc","p2":"def"}' 115 | ) 116 | .to_return( 117 | body: '{"abc":"def"}', 118 | status: 200, 119 | headers: { 'Content-type' => 'application/json' } 120 | ) 121 | end 122 | 123 | subject { target.put(path, body) } 124 | 125 | let(:path) { '/k/guest/1/v1/path.json' } 126 | let(:body) { { 'p1' => 'abc', 'p2' => 'def' } } 127 | 128 | it { expect(subject).to eq 'abc' => 'def' } 129 | 130 | context 'fail to request' do 131 | before(:each) do 132 | stub_request( 133 | :put, 134 | 'https://example.cybozu.com/k/guest/1/v1/path.json' 135 | ) 136 | .with( 137 | headers: { 'X-Cybozu-Authorization' => 'QWRtaW5pc3RyYXRvcjpjeWJvenU=' }, 138 | body: '{"p1":"abc","p2":"def"}' 139 | ) 140 | .to_return( 141 | body: '{"message":"不正なJSON文字列です。","id":"1505999166-897850006","code":"CB_IJ01"}', 142 | status: 500 143 | ) 144 | end 145 | 146 | it { expect { subject }.to raise_error Kintone::KintoneError } 147 | end 148 | end 149 | 150 | describe '#delete' do 151 | before(:each) do 152 | stub_request( 153 | :delete, 154 | 'https://example.cybozu.com/k/guest/1/v1/path.json' 155 | ) 156 | .with( 157 | body: { 'p1' => 'abc', 'p2' => 'def' }.to_json, 158 | headers: { 'X-Cybozu-Authorization' => 'QWRtaW5pc3RyYXRvcjpjeWJvenU=' } 159 | ) 160 | .to_return( 161 | body: '{"abc":"def"}', 162 | status: 200, 163 | headers: { 'Content-type' => 'application/json' } 164 | ) 165 | end 166 | 167 | subject { target.delete(path, params) } 168 | 169 | let(:path) { '/k/guest/1/v1/path.json' } 170 | let(:params) { { 'p1' => 'abc', 'p2' => 'def' } } 171 | 172 | it { expect(subject).to eq 'abc' => 'def' } 173 | 174 | context 'fail to request' do 175 | before(:each) do 176 | stub_request( 177 | :delete, 178 | 'https://example.cybozu.com/k/guest/1/v1/path.json' 179 | ) 180 | .with( 181 | body: { 'p1' => 'abc', 'p2' => 'def' }.to_json, 182 | headers: { 'X-Cybozu-Authorization' => 'QWRtaW5pc3RyYXRvcjpjeWJvenU=' } 183 | ) 184 | .to_return( 185 | body: '{"message":"不正なJSON文字列です。","id":"1505999166-897850006","code":"CB_IJ01"}', 186 | status: 500 187 | ) 188 | end 189 | 190 | it { expect { subject }.to raise_error Kintone::KintoneError } 191 | end 192 | end 193 | 194 | describe '#record' do 195 | subject { target.record } 196 | 197 | it { expect(subject).to be_a_kind_of(Kintone::Command::Record) } 198 | end 199 | 200 | describe '#records' do 201 | subject { target.records } 202 | 203 | it { expect(subject).to be_a_kind_of(Kintone::Command::Records) } 204 | end 205 | 206 | describe '#form' do 207 | subject { target.form } 208 | 209 | it { expect(subject).to be_a_kind_of(Kintone::Command::Form) } 210 | end 211 | 212 | describe '#app_acl' do 213 | subject { target.app_acl } 214 | 215 | it { expect(subject).to be_a_kind_of(Kintone::Command::AppAcl) } 216 | end 217 | 218 | describe '#record_acl' do 219 | subject { target.record_acl } 220 | 221 | it { expect(subject).to be_a_kind_of(Kintone::Command::RecordAcl) } 222 | end 223 | 224 | describe '#field_acl' do 225 | subject { target.field_acl } 226 | 227 | it { expect(subject).to be_a_kind_of(Kintone::Command::FieldAcl) } 228 | end 229 | 230 | describe '#space' do 231 | subject { target.space } 232 | 233 | it { expect(subject).to be_a_kind_of(Kintone::Command::Space) } 234 | end 235 | 236 | describe '#space_body' do 237 | subject { target.space_body } 238 | 239 | it { expect(subject).to be_a_kind_of(Kintone::Command::SpaceBody) } 240 | end 241 | 242 | describe '#space_thread' do 243 | subject { target.space_thread } 244 | 245 | it { expect(subject).to be_a_kind_of(Kintone::Command::SpaceThread) } 246 | end 247 | 248 | describe '#space_members' do 249 | subject { target.space_members } 250 | 251 | it { expect(subject).to be_a_kind_of(Kintone::Command::SpaceMembers) } 252 | end 253 | 254 | describe '#space_guests' do 255 | subject { target.space_guests } 256 | 257 | it { expect(subject).to be_a_kind_of(Kintone::Command::SpaceGuests) } 258 | end 259 | 260 | describe '#app' do 261 | subject { target.app } 262 | 263 | it { is_expected.to be_a_kind_of(Kintone::Command::App) } 264 | end 265 | 266 | describe '#apps' do 267 | subject { target.apps } 268 | 269 | it { is_expected.to be_a_kind_of(Kintone::Command::Apps) } 270 | end 271 | 272 | describe '#bulk_request' do 273 | subject { target.bulk_request } 274 | 275 | it { is_expected.to be_a_kind_of(Kintone::Command::BulkRequest) } 276 | end 277 | 278 | describe '#bulk' do 279 | subject { target.bulk } 280 | 281 | it { is_expected.to be_a_kind_of(Kintone::Command::BulkRequest) } 282 | end 283 | 284 | describe '#preview_form' do 285 | subject { target.preview_form } 286 | 287 | it { is_expected.to be_a_kind_of(Kintone::Command::PreviewForm) } 288 | end 289 | end 290 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # kintone 2 | 3 | [![Build Status](https://travis-ci.org/jue58/kintone.svg?branch=master)](https://travis-ci.org/jue58/kintone) 4 | [![codebeat badge](https://codebeat.co/badges/7f66de05-57a4-4712-9706-0f33169f530b)](https://codebeat.co/projects/github-com-jue58-kintone) 5 | [![Coverage Status](https://coveralls.io/repos/github/jue58/kintone/badge.svg?branch=add-coveralls-settings)](https://coveralls.io/github/jue58/kintone?branch=add-coveralls-settings) 6 | [![Inline docs](http://inch-ci.org/github/jue58/kintone.svg?branch=master&style=shields)](http://inch-ci.org/github/jue58/kintone) 7 | [![Gem Version](https://badge.fury.io/rb/kintone.svg)](https://badge.fury.io/rb/kintone) 8 | 9 | A Ruby gem for communicating with the [kintone](https://kintone.cybozu.com/us/) REST API 10 | 11 | ## Requirements 12 | 13 | - ruby 2.1.0 or later 14 | 15 | ## Installation 16 | 17 | gem install kintone 18 | 19 | or execute `bundle install` command after you insert the following into Gemfile 20 | 21 | gem 'kintone' 22 | 23 | ## Usage 24 | 25 | ```ruby 26 | require 'kintone' 27 | 28 | # Use password authentication 29 | api = Kintone::Api.new("example.cybozu.com", "Administrator", "cybozu") 30 | 31 | # Use token authentication 32 | api = Kintone::Api.new("example.cybozu.com", "authtoken") 33 | ``` 34 | 35 | ### Supported API 36 | - [Record retrieval](#record_retrieval) 37 | - [Record register](#record_register) 38 | - [Record update](#record_update) 39 | - [Record delete](#record_delete) 40 | - [Bulk request](#bulk_request) 41 | - [File](#file) 42 | - [Permissions](#permissions) 43 | - [Space management](#space_management) 44 | - [Guests](#guests) 45 | - [Application information](#application_information) 46 | - [Form structure](#form_structure) 47 | - [API information](#api_information) 48 | 49 | ### Record retrieval 50 | 51 | ```ruby 52 | # Record retrieval(Assign by Record Number) 53 | app = 8; id = 100 54 | api.record.get(app, id) # => {"record" => {"record_id" => {"type" => "RECORD_NUMBER", "value" => "1"}}} 55 | 56 | # Records retrieval(Assign by Conditions by Query Strings) 57 | app = 8; fields = ["record_id", "created_time", "dropdown"] 58 | query = "updated_time > \"2012-02-03T09:00:00+0900\" and updated_time < \"2012-02-03T10:00:00+0900\" order by record_id asc limit 10 offset 20" 59 | api.records.get(app, query, fields) # => {"records" => [{...}, ...]} 60 | ``` 61 | 62 | Query helper 63 | 64 | ```ruby 65 | query = 66 | Kintone::Query.new do 67 | field(:updated_time) > "2012-02-03T09:00:00+0900" 68 | and! 69 | field(:updated_time) < "2012-02-03T10:00:00+0900" 70 | order_by(:record_id) 71 | limit(10) 72 | offset(20) 73 | end 74 | # or 75 | query = 76 | Kintone::Query.new do 77 | f(:updated_time) > "2012-02-03T09:00:00+0900" 78 | and! 79 | f(:updated_time) < "2012-02-03T10:00:00+0900" 80 | order_by(:record_id) 81 | limit(10) 82 | offset(20) 83 | end 84 | query.to_s # => "updated_time > \"2012-02-03T09:00:00+0900\" and updated_time < \"2012-02-03T10:00:00+0900\" order by record_id asc limit 10 offset 20" 85 | api.records.get(app, query, fields) 86 | 87 | # Example 88 | Kintone::Query.new do 89 | field(:Created_datetime) >= last_month 90 | and! 91 | precede do 92 | field(:text).like("Hello") 93 | and! 94 | field(:number) == 200 95 | end 96 | or! 97 | precede do 98 | field(:number) > 100 99 | and! 100 | field(:Created_by).in([login_user]) 101 | end 102 | order_by(:record_id, :desc) 103 | limit(10) 104 | offset(20) 105 | end 106 | # => "Created_datetime >= LAST_MONTH() and (text like \"Hello\" and number = 200) or (number > 100 and Created_by in (LOGINUSER())) order by record_id desc limit 10 offset 20" 107 | ``` 108 | 109 | operator symbol | query helper 110 | --- | --- 111 | = | field(:code) == other 112 | != | field(:code) != other 113 | > | field(:code) > other 114 | < | field(:code) < other 115 | >= | field(:code) >= other 116 | <= | field(:code) <= other 117 | in | field(:code).in(["A", "B"]) 118 | not in | field(:code).not_in(["A", "B"]) 119 | like | field(:code).like("Hello") 120 | not like | field(:code).not_like("Hello") 121 | and | and! 122 | or | or! 123 | () | precede do; end 124 | 125 | function | query helper 126 | --- | --- 127 | LOGINUSER() | login_user 128 | PRIMARY_ORGANIZATION() | primary_organization 129 | NOW() | now 130 | TODAY() | today 131 | THIS_MONTH() | this_month 132 | LAST_MONTH() | last_month 133 | THIS_YEAR() | this_year 134 | 135 | option | query helper 136 | --- | --- 137 | order by | order_by(:code, :asc or :desc) 138 | limit | limit(20) 139 | offset | offset(30) 140 | 141 | ### Record register 142 | 143 | ```ruby 144 | # Record register(single record) 145 | # Use Hash 146 | app = 7 147 | record = {"number" => {"value" => "123456"}} 148 | api.record.register(app, record) # => {"id" => "100", "revision" => "1"} 149 | 150 | # Use Kintone::Type::Record 151 | app = 7 152 | record = Kintone::Type::Record.new(number: "123456") 153 | api.record.register(app, record) # => {"id" => "100", "revision" => "1"} 154 | 155 | # Records register(batch) 156 | # Use Hash 157 | app = 7 158 | records = [ 159 | {"number" => {"value" => "123456"}}, 160 | {"number" => {"value" => "7890"}} 161 | ] 162 | api.records.register(app, records) # => {"ids" => ["100", "101"], "revisions" => ["1", "1"]} 163 | 164 | # Use Kintone::Type::Record 165 | app = 7 166 | records = [ 167 | Kintone::Type::Record.new(number: "123456"), 168 | Kintone::Type::Record.new(number: "7890") 169 | ] 170 | api.records.register(app, records) # => {"ids" => ["100", "101"], "revisions" => ["1", "1"]} 171 | ``` 172 | 173 | ### Record update 174 | 175 | ```ruby 176 | # Record update(single record) 177 | # Use Hash 178 | app = 4; id = 1 179 | record = {"string_multi" => {"value" => "changed!"}} 180 | api.record.update(app, id, record) # => {"revision" => "2"} 181 | 182 | # Use Kintone::Type::Record 183 | app = 4; id = 1 184 | record = Kintone::Type::Record.new({string_multi: "changed!"}) 185 | api.record.update(app, id, record) # => {"revision" => "2"} 186 | 187 | # With revision 188 | api.record.update(app, id, record, revision: 1) 189 | 190 | # Records update(batch) 191 | # Use Hash 192 | app = 4 193 | records = [ 194 | {"id" => 1, "record" => {"string_multi" => {"value" => "abcdef"}}}, 195 | {"id" => 2, "record" => {"string_multi" => {"value" => "opqrstu"}}} 196 | ] 197 | api.records.update(app, records) # => {"records" => [{"id" => "1", "revision" => "2"}, {"id" => "2", "revision" => "2"}]} 198 | 199 | # Use Kintone::Type::Record 200 | app = 4 201 | records = [ 202 | {id: 1, record: Kintone::Type::Record.new(string_multi: "abcdef")}, 203 | {id: 2, record: Kintone::Type::Record.new(string_multi: "opqrstu")} 204 | ] 205 | api.records.update(app, records) # => {"records" => [{"id" => "1", "revision" => "2"}, {"id" => "2", "revision" => "2"}]} 206 | 207 | # with revision 208 | records = [ 209 | {id: 1, revision: 1, record: Kintone::Type::Record.new(string_multi: "abcdef")}, 210 | {id: 2, revision: 1, record: Kintone::Type::Record.new(string_multi: "opqrstu")} 211 | ] 212 | api.records.update(app, records) 213 | ``` 214 | 215 | ### Record delete 216 | 217 | ```ruby 218 | app = 8; ids = [100, 80] 219 | api.records.delete(app, ids) # => {} 220 | 221 | # With revision 222 | revisions = [1, 1] 223 | api.records.delete(app, ids, revisions: revisions) 224 | ``` 225 | 226 | ### Bulk request 227 | 228 | ```ruby 229 | requests = [{"method" => "POST", ...}, {"method" => "PUT", ...}] 230 | api.bulk.request(requests) # => [...] 231 | ``` 232 | 233 | ### File 234 | 235 | ```ruby 236 | # File upload 237 | file_key = api.file.register("/path/to/file", "text/plain", "file.txt") 238 | 239 | # File download 240 | file = api.file.get(file_key) 241 | ``` 242 | 243 | ### Permissions 244 | 245 | ```ruby 246 | # App 247 | app = 1 248 | rights = [{"entity" => {"type" => "USER", "code" => "user1"}, "appEditable" => true, ...}, ...] 249 | api.app_acl.update(app, rights) # => {} 250 | 251 | # Records 252 | id = 1 253 | rights = [{"filterCond" => "...", "entities" => [{"entity" => {...}, "viewable" => false, ...}, ...]}, ...] 254 | api.record_acl.update(id, rights) # => {} 255 | 256 | #Fields 257 | id = 1 258 | rights = [{"code" => "Single_line_text_0", "entities" => [{"entity" => {...}, "accesibility" => "WRITE"}, ...]}, ...] 259 | api.field_acl.update(id, rights) # => {} 260 | ``` 261 | 262 | ### Space management 263 | 264 | ```ruby 265 | # Space information 266 | id = 1 267 | api.space.get(id) # => { "id" => "1", "name" => "space", "defaultThread" => "3", "isPrivate" => true, ...} 268 | 269 | # Create space 270 | id = 1; name = "sample space" 271 | members = [{"entity" => {"type" => "USER", "code" => "user1"}, "isAdmin": true}, ...] 272 | api.template_space.create(id, name, members, is_guest: true, fixed_member: false) # => {"id" => "1"} 273 | 274 | # Space body update 275 | id = 1; body = "awesome space!" 276 | api.space_body.update(id, body) # => {} 277 | 278 | # Space members 279 | id = 1 280 | members = api.space_members.get(id) # => {"members"=>[{"entity"=>{"type"=>"USER", "code"=> "user1"}, ...}, ...]} 281 | members << {"entity" => {"type" => "GROUP", "code" => "group1"}} 282 | members = api.space_members.update(id, members) # => {} 283 | 284 | # Space thread update 285 | id = 1; name = "thread name" 286 | body = "awesome thread!" 287 | api.space_thread.update(id, name: name, body: body) # => {} 288 | 289 | # Space guests 290 | id = 1 291 | guests = ["hoge@example.com"] 292 | api.guest(1).space_guests.update(id, guests) # => {} 293 | 294 | # Space delete 295 | id = 1 296 | api.space.delete(id) # => {} 297 | ``` 298 | 299 | ### Guests 300 | 301 | ```ruby 302 | # Add guest 303 | guests = [{code: "hoge@example.com", password: "p@ssword", timezone: "Asia/Tokyo", name: "Tokyo, Saburo", ...}, ...] 304 | api.guests.register(guests) # => {} 305 | 306 | # delete guest 307 | guests = ["hoge@example.com", "fuga@example.com"] 308 | api.guests.delete(guests) # => {} 309 | ``` 310 | 311 | ### Application information 312 | 313 | ```ruby 314 | id = 4 315 | api.app.get(id) # => {"appId" => "4", "code" => "", ...} 316 | 317 | name = "test"; codes = ["FOO", "BAR"] 318 | api.apps.get({ name: name, codes: codes }) # => { "apps" => [{...}, ...] } 319 | ``` 320 | 321 | ### Form structure 322 | 323 | ```ruby 324 | app = 1 325 | api.form.get(app) # => {"properties" => [{...}, ...]} 326 | 327 | api.preview_form.get(app) # => {"properties" => [{...}, ...]} 328 | ``` 329 | 330 | ### API information 331 | 332 | ```ruby 333 | api.apis.get # => {"baseUrl" => "https://example.cybozu.com/k/v1/", "apis" => {"records/get" => {"link" => "apis/records/get.json"}}} 334 | 335 | api.apis.get_details_of("apis/records/get.json") # => {"id" => "GetRecords", "baseUrl" => "https://example.cybozu.com/k/v1/", ...} 336 | 337 | api.apis.get_details_of_key("records/get") # => {"id" => "GetRecords", "baseUrl" => "https://example.cybozu.com/k/v1/", ...} 338 | ``` 339 | 340 | ### Other examples 341 | 342 | ```ruby 343 | # Format retrieval 344 | url = api.get_url("form") 345 | api.get(url, {"app" => 4}) # => {"properties" => [{...}, ...]} 346 | 347 | # Batch record register 348 | url = api.get_url("records") 349 | body = {"app" => 7, "records" => [{...}, ...]} 350 | api.post(url, body) # => {"ids" => ["100","101"]} 351 | ``` 352 | 353 | ### Access to guest spaces 354 | 355 | ```ruby 356 | api.guest(1).record.get(8, 100) 357 | ``` 358 | 359 | see also [kintone developers](http://developers.kintone.com/) 360 | -------------------------------------------------------------------------------- /spec/kintone/command/records_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | require 'kintone/command/records' 3 | require 'kintone/api' 4 | require 'kintone/type' 5 | 6 | describe Kintone::Command::Records do 7 | let(:target) { Kintone::Command::Records.new(api) } 8 | let(:api) { Kintone::Api.new('example.cybozu.com', 'Administrator', 'cybozu') } 9 | 10 | describe '#get' do 11 | subject { target.get(app, query, fields) } 12 | 13 | let(:app) { 8 } 14 | let(:query) { '' } 15 | let(:fields) { [] } 16 | let(:request_body) { { app: app, query: query.to_s, totalCount: false, fields: fields } } 17 | 18 | context 'アプリIDだけ指定した時' do 19 | let(:response_data) do 20 | { 21 | 'records' => [{ 'record_id' => { 'type' => 'RECORD_NUMBER', 'value' => '1' } }], 22 | 'totalCount' => nil 23 | } 24 | end 25 | 26 | before(:each) do 27 | stub_request( 28 | :get, 29 | 'https://example.cybozu.com/k/v1/records.json' 30 | ) 31 | .with(body: request_body.to_json) 32 | .to_return( 33 | body: response_data.to_json, 34 | status: 200, 35 | headers: { 'Content-type' => 'application/json' } 36 | ) 37 | end 38 | 39 | it { expect(subject).to eq response_data } 40 | end 41 | 42 | context '条件に文字列を含むqueryを指定した時' do 43 | before(:each) do 44 | stub_request( 45 | :get, 46 | 'https://example.cybozu.com/k/v1/records.json' 47 | ) 48 | .with(body: request_body.to_json) 49 | .to_return( 50 | body: response_data.to_json, 51 | status: 200, 52 | headers: { 'Content-type' => 'application/json' } 53 | ) 54 | end 55 | 56 | let(:query) { 'updated_time > "2012-02-03T09:00:00+0900" and updated_time < "2012-02-03T10:00:00+0900"' } # rubocop:disable Metrics/LineLength 57 | let(:response_data) do 58 | { 59 | 'records' => [{ 'record_id' => { 'type' => 'RECORD_NUMBER', 'value' => '1' } }], 60 | 'totalCount' => nil 61 | } 62 | end 63 | 64 | it { expect(subject).to eq response_data } 65 | end 66 | 67 | context '項目に全角文字を含むfieldsを指定した時' do 68 | before(:each) do 69 | stub_request( 70 | :get, 71 | 'https://example.cybozu.com/k/v1/records.json' 72 | ) 73 | .with(body: request_body.to_json) 74 | .to_return( 75 | body: response_data.to_json, 76 | status: 200, 77 | headers: { 'Content-type' => 'application/json' } 78 | ) 79 | end 80 | 81 | let(:fields) { %w(レコード番号 created_time dropdown) } 82 | let(:response_data) do 83 | { 84 | 'records' => [{ 'record_id' => { 'type' => 'RECORD_NUMBER', 'value' => '1' } }], 85 | 'totalCount' => nil 86 | } 87 | end 88 | 89 | it { expect(subject).to eq response_data } 90 | end 91 | 92 | context 'queryにnilを指定した時' do 93 | before(:each) do 94 | stub_request( 95 | :get, 96 | 'https://example.cybozu.com/k/v1/records.json' 97 | ) 98 | .with(body: request_body.to_json) 99 | .to_return( 100 | body: response_data.to_json, 101 | status: 200, 102 | headers: { 'Content-type' => 'application/json' } 103 | ) 104 | end 105 | 106 | let(:query) { nil } 107 | let(:response_data) do 108 | { 109 | 'records' => [{ 'record_id' => { 'type' => 'RECORD_NUMBER', 'value' => '1' } }], 110 | 'totalCount' => nil 111 | } 112 | end 113 | 114 | it { expect(subject).to eq response_data } 115 | end 116 | 117 | context 'fieldsにnilを指定した時' do 118 | let(:fields) { nil } 119 | let(:request_body) { { app: app, query: query, totalCount: false } } 120 | let(:response_data) do 121 | { 122 | 'records' => [{ 'record_id' => { 'type' => 'RECORD_NUMBER', 'value' => '1' } }], 123 | 'totalCount' => nil 124 | } 125 | end 126 | 127 | before(:each) do 128 | stub_request( 129 | :get, 130 | 'https://example.cybozu.com/k/v1/records.json' 131 | ) 132 | .with(body: request_body.to_json) 133 | .to_return( 134 | body: response_data.to_json, 135 | status: 200, 136 | headers: { 'Content-type' => 'application/json' } 137 | ) 138 | end 139 | 140 | it { expect(subject).to eq response_data } 141 | end 142 | 143 | context 'totalCountにtrueを指定した時' do 144 | before(:each) do 145 | stub_request( 146 | :get, 147 | 'https://example.cybozu.com/k/v1/records.json' 148 | ) 149 | .with(body: request_body.to_json) 150 | .to_return( 151 | body: response_data.to_json, 152 | status: 200, 153 | headers: { 'Content-type' => 'application/json' } 154 | ) 155 | end 156 | 157 | subject { target.get(app, query, fields, total_count: total_count) } 158 | 159 | let(:request_body) { { app: app, query: query, totalCount: total_count, fields: fields } } 160 | let(:response_data) do 161 | { 162 | 'records' => [{ 'record_id' => { 'type' => 'RECORD_NUMBER', 'value' => '1' } }], 163 | 'totalCount' => '1' 164 | } 165 | end 166 | 167 | let(:total_count) { true } 168 | it { expect(subject).to eq response_data } 169 | end 170 | 171 | context 'fail to request' do 172 | before(:each) do 173 | stub_request( 174 | :get, 175 | 'https://example.cybozu.com/k/v1/records.json' 176 | ) 177 | .with(body: request_body.to_json) 178 | .to_return( 179 | body: '{"message":"不正なJSON文字列です。","id":"1505999166-897850006","code":"CB_IJ01"}', 180 | status: 500, 181 | headers: { 'Content-Type' => 'application/json' } 182 | ) 183 | end 184 | let(:fields) { nil } 185 | let(:request_body) { { app: app, query: '', totalCount: false } } 186 | 187 | it { expect { subject }.to raise_error Kintone::KintoneError } 188 | end 189 | end 190 | 191 | describe '#register' do 192 | before(:each) do 193 | stub_request( 194 | :post, 195 | 'https://example.cybozu.com/k/v1/records.json' 196 | ) 197 | .with(body: request_body.to_json) 198 | .to_return( 199 | body: response_body.to_json, 200 | status: 200, 201 | headers: { 'Content-type' => 'application/json' } 202 | ) 203 | end 204 | 205 | subject { target.register(app, records) } 206 | 207 | let(:app) { 7 } 208 | let(:request_body) do 209 | { 210 | 'app' => 7, 211 | 'records' => [ 212 | { 'rich_editor' => { 'value' => 'testtest' } }, 213 | { 'user_select' => { 'value' => [{ 'code' => 'suzuki' }] } } 214 | ] 215 | } 216 | end 217 | let(:response_body) { { 'ids' => ['100', '101'], 'revisions' => ['1', '1'] } } 218 | 219 | context 'use hash' do 220 | let(:records) do 221 | [ 222 | { 'rich_editor' => { 'value' => 'testtest' } }, 223 | { 'user_select' => { 'value' => [{ 'code' => 'suzuki' }] } } 224 | ] 225 | end 226 | 227 | it { expect(subject).to eq response_body } 228 | end 229 | 230 | context 'use record' do 231 | let(:records) do 232 | [ 233 | Kintone::Type::Record.new(rich_editor: 'testtest'), 234 | Kintone::Type::Record.new(user_select: [{ code: 'suzuki' }]) 235 | ] 236 | end 237 | 238 | it { expect(subject).to eq response_body } 239 | end 240 | 241 | context 'fail to request' do 242 | before(:each) do 243 | stub_request( 244 | :post, 245 | 'https://example.cybozu.com/k/v1/records.json' 246 | ) 247 | .with(body: request_body.to_json) 248 | .to_return( 249 | body: '{"message":"不正なJSON文字列です。","id":"1505999166-897850006","code":"CB_IJ01"}', 250 | status: 500, 251 | headers: { 'Content-Type' => 'application/json' } 252 | ) 253 | end 254 | 255 | let(:records) do 256 | [ 257 | { 'rich_editor' => { 'value' => 'testtest' } }, 258 | { 'user_select' => { 'value' => [{ 'code' => 'suzuki' }] } } 259 | ] 260 | end 261 | 262 | it { expect { subject }.to raise_error Kintone::KintoneError } 263 | end 264 | end 265 | 266 | describe '#update' do 267 | before(:each) do 268 | stub_request( 269 | :put, 270 | 'https://example.cybozu.com/k/v1/records.json' 271 | ) 272 | .with(body: request_body.to_json) 273 | .to_return( 274 | body: response_body.to_json, 275 | status: 200, 276 | headers: { 'Content-type' => 'application/json' } 277 | ) 278 | end 279 | 280 | subject { target.update(app, records) } 281 | 282 | let(:app) { 4 } 283 | let(:response_body) do 284 | { 'records' => [{ 'id' => '1', 'revision' => '2' }, { 'id' => '2', 'revision' => '2' }] } 285 | end 286 | 287 | context 'without revision' do 288 | let(:request_body) do 289 | { 290 | 'app' => 4, 291 | 'records' => [ 292 | { 'id' => 1, 'record' => { 'string_1' => { 'value' => 'abcdef' } } }, 293 | { 'id' => 2, 'record' => { 'string_multi' => { 'value' => 'opqrstu' } } } 294 | ] 295 | } 296 | end 297 | 298 | context 'use hash' do 299 | let(:records) do 300 | [ 301 | { 'id' => 1, 'record' => { 'string_1' => { 'value' => 'abcdef' } } }, 302 | { 'id' => 2, 'record' => { 'string_multi' => { 'value' => 'opqrstu' } } } 303 | ] 304 | end 305 | 306 | it { expect(subject).to eq response_body } 307 | end 308 | 309 | context 'use record' do 310 | let(:records) do 311 | [ 312 | { id: 1, record: Kintone::Type::Record.new(string_1: 'abcdef') }, 313 | { id: 2, record: Kintone::Type::Record.new(string_multi: 'opqrstu') } 314 | ] 315 | end 316 | 317 | it { expect(subject).to eq response_body } 318 | end 319 | end 320 | 321 | context 'with revision' do 322 | let(:request_body) do 323 | { 324 | 'app' => 4, 325 | 'records' => [ 326 | { 327 | 'id' => 1, 328 | 'revision' => 1, 329 | 'record' => { 'string_1' => { 'value' => 'abcdef' } } 330 | }, 331 | { 332 | 'id' => 2, 333 | 'revision' => 1, 334 | 'record' => { 'string_multi' => { 'value' => 'opqrstu' } } 335 | } 336 | ] 337 | } 338 | end 339 | 340 | context 'use hash' do 341 | let(:records) do 342 | [ 343 | { 344 | 'id' => 1, 345 | 'revision' => 1, 346 | 'record' => { 'string_1' => { 'value' => 'abcdef' } } 347 | }, 348 | { 349 | 'id' => 2, 350 | 'revision' => 1, 351 | 'record' => { 'string_multi' => { 'value' => 'opqrstu' } } 352 | } 353 | ] 354 | end 355 | 356 | it { expect(subject).to eq response_body } 357 | end 358 | 359 | context 'use record' do 360 | let(:records) do 361 | [ 362 | { id: 1, revision: 1, record: Kintone::Type::Record.new(string_1: 'abcdef') }, 363 | { id: 2, revision: 1, record: Kintone::Type::Record.new(string_multi: 'opqrstu') } 364 | ] 365 | end 366 | 367 | it { expect(subject).to eq response_body } 368 | end 369 | end 370 | 371 | context 'fail to request' do 372 | before(:each) do 373 | stub_request( 374 | :put, 375 | 'https://example.cybozu.com/k/v1/records.json' 376 | ) 377 | .with(body: request_body.to_json) 378 | .to_return( 379 | body: '{"message":"不正なJSON文字列です。","id":"1505999166-897850006","code":"CB_IJ01"}', 380 | status: 500, 381 | headers: { 'Content-Type' => 'application/json' } 382 | ) 383 | end 384 | 385 | let(:records) do 386 | [ 387 | { 'id' => 1, 'record' => { 'string_1' => { 'value' => 'abcdef' } } }, 388 | { 'id' => 2, 'record' => { 'string_multi' => { 'value' => 'opqrstu' } } } 389 | ] 390 | end 391 | let(:request_body) do 392 | { 393 | 'app' => 4, 394 | 'records' => [ 395 | { 'id' => 1, 'record' => { 'string_1' => { 'value' => 'abcdef' } } }, 396 | { 'id' => 2, 'record' => { 'string_multi' => { 'value' => 'opqrstu' } } } 397 | ] 398 | } 399 | end 400 | 401 | it { expect { subject }.to raise_error Kintone::KintoneError } 402 | end 403 | end 404 | 405 | describe '#delete' do 406 | before(:each) do 407 | stub_request( 408 | :delete, 409 | 'https://example.cybozu.com/k/v1/records.json' 410 | ) 411 | .with(body: request_body.to_json) 412 | .to_return( 413 | body: '{}', 414 | status: 200, 415 | headers: { 'Content-type' => 'application/json' } 416 | ) 417 | end 418 | 419 | context 'without revisions' do 420 | subject { target.delete(app, ids) } 421 | 422 | let(:app) { 1 } 423 | let(:ids) { [100, 80] } 424 | let(:request_body) { { app: app, ids: ids } } 425 | 426 | it { expect(subject).to eq({}) } 427 | end 428 | 429 | context 'with revisions' do 430 | subject { target.delete(app, ids, revisions: revisions) } 431 | 432 | let(:app) { 1 } 433 | let(:ids) { [100, 80] } 434 | let(:revisions) { [1, 4] } 435 | let(:request_body) { { app: app, ids: ids, revisions: revisions } } 436 | 437 | it { expect(subject).to eq({}) } 438 | end 439 | 440 | context 'fail to request' do 441 | before(:each) do 442 | stub_request( 443 | :delete, 444 | 'https://example.cybozu.com/k/v1/records.json' 445 | ) 446 | .with(body: request_body.to_json) 447 | .to_return( 448 | body: '{"message":"不正なJSON文字列です。","id":"1505999166-897850006","code":"CB_IJ01"}', 449 | status: 500, 450 | headers: { 'Content-Type' => 'application/json' } 451 | ) 452 | end 453 | 454 | subject { target.delete(app, ids) } 455 | 456 | let(:app) { 1 } 457 | let(:ids) { [100, 80] } 458 | let(:request_body) { { app: app, ids: ids } } 459 | 460 | it { expect { subject }.to raise_error Kintone::KintoneError } 461 | end 462 | end 463 | end 464 | -------------------------------------------------------------------------------- /spec/kintone/api_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | require 'kintone/api' 3 | require 'kintone/api/guest' 4 | require 'kintone/command/record' 5 | require 'kintone/command/records' 6 | 7 | describe Kintone::Api do 8 | let(:target) { Kintone::Api.new(domain, user, password) } 9 | let(:domain) { 'www.example.com' } 10 | 11 | context 'ユーザー認証の時' do 12 | let(:user) { 'Administrator' } 13 | let(:password) { 'cybozu' } 14 | 15 | describe '#get_url' do 16 | subject { target.get_url(command) } 17 | 18 | let(:command) { 'path' } 19 | 20 | it { is_expected.to eq('/k/v1/path.json') } 21 | end 22 | 23 | describe '#guest' do 24 | subject { target.guest(space) } 25 | 26 | context '引数が数値の1の時' do 27 | let(:space) { 1 } 28 | 29 | it { is_expected.to be_a_kind_of(Kintone::Api::Guest) } 30 | it { expect(subject.instance_variable_get(:@guest_path)).to eq('/k/guest/1/v1/') } 31 | end 32 | 33 | context '引数がnilの時' do 34 | let(:space) { nil } 35 | it { expect(subject.instance_variable_get(:@guest_path)).to eq('/k/guest/0/v1/') } 36 | end 37 | 38 | context '引数が数字の時' do 39 | let(:space) { '2.1' } 40 | it { expect(subject.instance_variable_get(:@guest_path)).to eq('/k/guest/2/v1/') } 41 | end 42 | 43 | context '引数が数値に変換できる文字列の時' do 44 | let(:space) { '21No' } 45 | it { expect(subject.instance_variable_get(:@guest_path)).to eq('/k/guest/21/v1/') } 46 | end 47 | 48 | context '引数が数値に変換できる文字列でないとき時' do 49 | let(:space) { 'No21' } 50 | it { expect(subject.instance_variable_get(:@guest_path)).to eq('/k/guest/0/v1/') } 51 | end 52 | end 53 | 54 | describe '#get' do 55 | before(:each) do 56 | stub_request( 57 | :get, 58 | 'https://www.example.com/k/v1/path' 59 | ) 60 | .with( 61 | body: params.to_h.to_json, 62 | headers: { 'X-Cybozu-Authorization' => 'QWRtaW5pc3RyYXRvcjpjeWJvenU=' } 63 | ) 64 | .to_return( 65 | body: '{"abc":"def"}', 66 | status: 200, 67 | headers: { 'Content-type' => 'application/json' } 68 | ) 69 | end 70 | 71 | subject { target.get(path, params) } 72 | 73 | let(:path) { '/k/v1/path' } 74 | 75 | context 'with some params' do 76 | let(:params) { { 'p1' => 'abc', 'p2' => 'def' } } 77 | 78 | it { is_expected.to eq 'abc' => 'def' } 79 | end 80 | 81 | context 'with empty params' do 82 | let(:params) { {} } 83 | 84 | it { is_expected.to eq 'abc' => 'def' } 85 | end 86 | 87 | context 'with nil' do 88 | let(:params) { nil } 89 | 90 | it { is_expected.to eq 'abc' => 'def' } 91 | end 92 | 93 | context 'fail to request' do 94 | before(:each) do 95 | stub_request( 96 | :get, 97 | 'https://www.example.com/k/v1/path' 98 | ) 99 | .with( 100 | body: params.to_json, 101 | headers: { 'X-Cybozu-Authorization' => 'QWRtaW5pc3RyYXRvcjpjeWJvenU=' } 102 | ) 103 | .to_return( 104 | body: '{"message":"不正なJSON文字列です。","id":"1505999166-897850006","code":"CB_IJ01"}', 105 | status: 500 106 | ) 107 | end 108 | 109 | let(:params) { {} } 110 | 111 | it { expect { subject }.to raise_error Kintone::KintoneError } 112 | end 113 | end 114 | 115 | describe '#post' do 116 | before(:each) do 117 | stub_request( 118 | :post, 119 | 'https://www.example.com/k/v1/path' 120 | ) 121 | .with( 122 | headers: { 123 | 'X-Cybozu-Authorization' => 'QWRtaW5pc3RyYXRvcjpjeWJvenU=', 124 | 'Content-Type' => 'application/json' 125 | }, 126 | body: '{"p1":"abc","p2":"def"}' 127 | ) 128 | .to_return( 129 | body: '{"abc":"def"}', 130 | status: 200, 131 | headers: { 'Content-type' => 'application/json' } 132 | ) 133 | end 134 | 135 | subject { target.post(path, body) } 136 | let(:path) { '/k/v1/path' } 137 | let(:body) { { 'p1' => 'abc', 'p2' => 'def' } } 138 | 139 | it { is_expected.to eq 'abc' => 'def' } 140 | 141 | context 'fail to request' do 142 | before(:each) do 143 | stub_request( 144 | :post, 145 | 'https://www.example.com/k/v1/path' 146 | ) 147 | .with( 148 | headers: { 149 | 'X-Cybozu-Authorization' => 'QWRtaW5pc3RyYXRvcjpjeWJvenU=', 150 | 'Content-Type' => 'application/json' 151 | }, 152 | body: '{"p1":"abc","p2":"def"}' 153 | ) 154 | .to_return( 155 | body: '{"message":"不正なJSON文字列です。","id":"1505999166-897850006","code":"CB_IJ01"}', 156 | status: 500 157 | ) 158 | end 159 | 160 | it { expect { subject }.to raise_error Kintone::KintoneError } 161 | end 162 | end 163 | 164 | describe '#put' do 165 | before(:each) do 166 | stub_request( 167 | :put, 168 | 'https://www.example.com/k/v1/path' 169 | ) 170 | .with( 171 | headers: { 172 | 'X-Cybozu-Authorization' => 'QWRtaW5pc3RyYXRvcjpjeWJvenU=', 173 | 'Content-Type' => 'application/json' 174 | }, 175 | body: '{"p1":"abc","p2":"def"}' 176 | ) 177 | .to_return( 178 | body: '{"abc":"def"}', 179 | status: 200, 180 | headers: { 'Content-type' => 'application/json' } 181 | ) 182 | end 183 | 184 | subject { target.put(path, body) } 185 | let(:path) { '/k/v1/path' } 186 | let(:body) { { 'p1' => 'abc', 'p2' => 'def' } } 187 | 188 | it { is_expected.to eq 'abc' => 'def' } 189 | 190 | context 'fail to request' do 191 | before(:each) do 192 | stub_request( 193 | :put, 194 | 'https://www.example.com/k/v1/path' 195 | ) 196 | .with( 197 | headers: { 198 | 'X-Cybozu-Authorization' => 'QWRtaW5pc3RyYXRvcjpjeWJvenU=', 199 | 'Content-Type' => 'application/json' 200 | }, 201 | body: '{"p1":"abc","p2":"def"}' 202 | ) 203 | .to_return( 204 | body: '{"message":"不正なJSON文字列です。","id":"1505999166-897850006","code":"CB_IJ01"}', 205 | status: 500 206 | ) 207 | end 208 | 209 | it { expect { subject }.to raise_error Kintone::KintoneError } 210 | end 211 | end 212 | 213 | describe '#delete' do 214 | before(:each) do 215 | stub_request( 216 | :delete, 217 | 'https://www.example.com/k/v1/path' 218 | ) 219 | .with( 220 | body: { 'p1' => 'abc', 'p2' => 'def' }.to_json, 221 | headers: { 'X-Cybozu-Authorization' => 'QWRtaW5pc3RyYXRvcjpjeWJvenU=' } 222 | ) 223 | .to_return( 224 | body: '{"abc":"def"}', 225 | status: 200, 226 | headers: { 'Content-type' => 'application/json' } 227 | ) 228 | end 229 | 230 | subject { target.delete(path, params) } 231 | let(:path) { '/k/v1/path' } 232 | let(:params) { { 'p1' => 'abc', 'p2' => 'def' } } 233 | 234 | it { is_expected.to eq 'abc' => 'def' } 235 | 236 | context 'fail to request' do 237 | before(:each) do 238 | stub_request( 239 | :delete, 240 | 'https://www.example.com/k/v1/path' 241 | ) 242 | .with( 243 | body: { 'p1' => 'abc', 'p2' => 'def' }.to_json, 244 | headers: { 'X-Cybozu-Authorization' => 'QWRtaW5pc3RyYXRvcjpjeWJvenU=' } 245 | ) 246 | .to_return( 247 | body: '{"message":"不正なJSON文字列です。","id":"1505999166-897850006","code":"CB_IJ01"}', 248 | status: 500 249 | ) 250 | end 251 | 252 | it { expect { subject }.to raise_error Kintone::KintoneError } 253 | end 254 | end 255 | 256 | describe '#post_file' do 257 | before(:each) do 258 | stub_request( 259 | :post, 260 | 'https://www.example.com/k/v1/path' 261 | ) 262 | .with(headers: { 'X-Cybozu-Authorization' => 'QWRtaW5pc3RyYXRvcjpjeWJvenU=' }) { attachment } # rubocop:disable Metrics/LineLength 263 | .to_return( 264 | body: '{"fileKey":"abc"}', 265 | status: 200, 266 | headers: { 'Content-type' => 'application/json' } 267 | ) 268 | 269 | expect(Faraday::UploadIO).to receive(:new).with(path, content_type, original_filename).and_return(attachment) # rubocop:disable Metrics/LineLength 270 | end 271 | 272 | subject { target.post_file(url, path, content_type, original_filename) } 273 | let(:attachment) { double('attachment') } 274 | let(:url) { '/k/v1/path' } 275 | let(:path) { '/path/to/file.txt' } 276 | let(:content_type) { 'text/plain' } 277 | let(:original_filename) { 'fileName.txt' } 278 | 279 | it { is_expected.to eq 'abc' } 280 | 281 | context 'fail to request' do 282 | before(:each) do 283 | stub_request( 284 | :post, 285 | 'https://www.example.com/k/v1/path' 286 | ) 287 | .with(headers: { 'X-Cybozu-Authorization' => 'QWRtaW5pc3RyYXRvcjpjeWJvenU=' }) { attachment } # rubocop:disable Metrics/LineLength 288 | .to_return( 289 | body: '{"message":"不正なJSON文字列です。","id":"1505999166-897850006","code":"CB_IJ01"}', 290 | status: 500 291 | ) 292 | end 293 | 294 | it { expect { subject }.to raise_error Kintone::KintoneError } 295 | end 296 | end 297 | 298 | describe '#record' do 299 | subject { target.record } 300 | 301 | it { is_expected.to be_a_kind_of(Kintone::Command::Record) } 302 | end 303 | 304 | describe '#records' do 305 | subject { target.records } 306 | 307 | it { is_expected.to be_a_kind_of(Kintone::Command::Records) } 308 | end 309 | 310 | describe '#form' do 311 | subject { target.form } 312 | 313 | it { is_expected.to be_a_kind_of(Kintone::Command::Form) } 314 | end 315 | 316 | describe '#app_acl' do 317 | subject { target.app_acl } 318 | 319 | it { is_expected.to be_a_kind_of(Kintone::Command::AppAcl) } 320 | end 321 | 322 | describe '#record_acl' do 323 | subject { target.record_acl } 324 | 325 | it { is_expected.to be_a_kind_of(Kintone::Command::RecordAcl) } 326 | end 327 | 328 | describe '#field_acl' do 329 | subject { target.field_acl } 330 | 331 | it { is_expected.to be_a_kind_of(Kintone::Command::FieldAcl) } 332 | end 333 | 334 | describe '#template_space' do 335 | subject { target.template_space } 336 | 337 | it { is_expected.to be_a_kind_of(Kintone::Command::TemplateSpace) } 338 | end 339 | 340 | describe '#space' do 341 | subject { target.space } 342 | 343 | it { is_expected.to be_a_kind_of(Kintone::Command::Space) } 344 | end 345 | 346 | describe '#space_body' do 347 | subject { target.space_body } 348 | 349 | it { is_expected.to be_a_kind_of(Kintone::Command::SpaceBody) } 350 | end 351 | 352 | describe '#space_thread' do 353 | subject { target.space_thread } 354 | 355 | it { is_expected.to be_a_kind_of(Kintone::Command::SpaceThread) } 356 | end 357 | 358 | describe '#space_members' do 359 | subject { target.space_members } 360 | 361 | it { is_expected.to be_a_kind_of(Kintone::Command::SpaceMembers) } 362 | end 363 | 364 | describe '#guests' do 365 | subject { target.guests } 366 | 367 | it { is_expected.to be_a_kind_of(Kintone::Command::Guests) } 368 | end 369 | 370 | describe '#app' do 371 | subject { target.app } 372 | 373 | it { is_expected.to be_a_kind_of(Kintone::Command::App) } 374 | end 375 | 376 | describe '#apps' do 377 | subject { target.apps } 378 | 379 | it { is_expected.to be_a_kind_of(Kintone::Command::Apps) } 380 | end 381 | 382 | describe '#apis' do 383 | subject { target.apis } 384 | 385 | it { is_expected.to be_a_kind_of(Kintone::Command::Apis) } 386 | end 387 | 388 | describe '#bulk_request' do 389 | subject { target.bulk_request } 390 | 391 | it { is_expected.to be_a_kind_of(Kintone::Command::BulkRequest) } 392 | end 393 | 394 | describe '#bulk' do 395 | subject { target.bulk } 396 | 397 | it { is_expected.to be_a_kind_of(Kintone::Command::BulkRequest) } 398 | end 399 | 400 | describe '#file' do 401 | subject { target.file } 402 | 403 | it { is_expected.to be_a_kind_of(Kintone::Command::File) } 404 | end 405 | 406 | describe '#preview_form' do 407 | subject { target.preview_form } 408 | 409 | it { is_expected.to be_a_kind_of(Kintone::Command::PreviewForm) } 410 | end 411 | end 412 | 413 | context 'APIトークン認証の時' do 414 | let(:user) { 'token-api' } 415 | let(:password) { nil } 416 | 417 | describe '#get' do 418 | before(:each) do 419 | stub_request( 420 | :get, 421 | 'https://www.example.com/k/v1/path' 422 | ) 423 | .with(query: query, headers: { 'X-Cybozu-API-Token' => 'token-api' }) 424 | .to_return( 425 | body: '{"abc":"def"}', 426 | status: 200, 427 | headers: { 'Content-type' => 'application/json' } 428 | ) 429 | end 430 | 431 | subject { target.get(path, params) } 432 | 433 | let(:path) { '/k/v1/path' } 434 | 435 | context 'with no params' do 436 | subject { target.get(path) } 437 | 438 | let(:query) { nil } 439 | 440 | it { is_expected.to eq 'abc' => 'def' } 441 | end 442 | end 443 | 444 | describe '#post' do 445 | before(:each) do 446 | stub_request( 447 | :post, 448 | 'https://www.example.com/k/v1/path' 449 | ) 450 | .with( 451 | headers: { 'X-Cybozu-API-Token' => 'token-api', 'Content-Type' => 'application/json' }, 452 | body: '{"p1":"abc","p2":"def"}' 453 | ) 454 | .to_return( 455 | body: '{"abc":"def"}', 456 | status: 200, 457 | headers: { 'Content-type' => 'application/json' } 458 | ) 459 | end 460 | 461 | subject { target.post(path, body) } 462 | let(:path) { '/k/v1/path' } 463 | let(:body) { { 'p1' => 'abc', 'p2' => 'def' } } 464 | 465 | it { is_expected.to eq 'abc' => 'def' } 466 | end 467 | 468 | describe '#put' do 469 | before(:each) do 470 | stub_request( 471 | :put, 472 | 'https://www.example.com/k/v1/path' 473 | ) 474 | .with( 475 | headers: { 'X-Cybozu-API-Token' => 'token-api', 'Content-Type' => 'application/json' }, 476 | body: '{"p1":"abc","p2":"def"}' 477 | ) 478 | .to_return( 479 | body: '{"abc":"def"}', 480 | status: 200, 481 | headers: { 'Content-type' => 'application/json' } 482 | ) 483 | end 484 | 485 | subject { target.put(path, body) } 486 | let(:path) { '/k/v1/path' } 487 | let(:body) { { 'p1' => 'abc', 'p2' => 'def' } } 488 | 489 | it { is_expected.to eq 'abc' => 'def' } 490 | end 491 | 492 | describe '#delete' do 493 | before(:each) do 494 | stub_request( 495 | :delete, 496 | 'https://www.example.com/k/v1/path' 497 | ) 498 | .with( 499 | body: { 'p1' => 'abc', 'p2' => 'def' }.to_json, 500 | headers: { 'X-Cybozu-API-Token' => 'token-api' } 501 | ) 502 | .to_return( 503 | body: '{"abc":"def"}', 504 | status: 200, 505 | headers: { 'Content-type' => 'application/json' } 506 | ) 507 | end 508 | 509 | subject { target.delete(path, params) } 510 | let(:path) { '/k/v1/path' } 511 | let(:params) { { 'p1' => 'abc', 'p2' => 'def' } } 512 | 513 | it { is_expected.to eq 'abc' => 'def' } 514 | end 515 | 516 | describe '#post_file' do 517 | before(:each) do 518 | stub_request( 519 | :post, 520 | 'https://www.example.com/k/v1/path' 521 | ) 522 | .with(headers: { 'X-Cybozu-API-Token' => 'token-api' }) 523 | .to_return( 524 | body: '{"fileKey":"abc"}', 525 | status: 200, 526 | headers: { 'Content-type' => 'application/json' } 527 | ) 528 | 529 | expect(Faraday::UploadIO).to receive(:new).with(path, content_type, original_filename).and_return(attachment) # rubocop:disable Metrics/LineLength 530 | end 531 | 532 | subject { target.post_file(url, path, content_type, original_filename) } 533 | let(:attachment) { double('attachment') } 534 | let(:url) { '/k/v1/path' } 535 | let(:path) { '/path/to/file.txt' } 536 | let(:content_type) { 'text/plain' } 537 | let(:original_filename) { 'fileName.txt' } 538 | 539 | it { is_expected.to eq 'abc' } 540 | end 541 | end 542 | 543 | describe '#new' do 544 | let(:domain) { 'www.example.com' } 545 | let(:user) { 'Administrator' } 546 | let(:password) { 'cybozu' } 547 | 548 | context 'ブロック引数が与えられていない時' do 549 | subject { api.instance_variable_get(:@connection).proxy } 550 | let(:api) { Kintone::Api.new(domain, user, password) } 551 | 552 | it { is_expected.to be_nil } 553 | end 554 | 555 | context 'ブロック引数が与えられている時' do 556 | subject { api.instance_variable_get(:@connection).proxy } 557 | let(:api) do 558 | Kintone::Api.new(domain, user, password) do |connection| 559 | connection.proxy = 'http://127.0.0.1' 560 | end 561 | end 562 | 563 | it { is_expected.to be_a Faraday::ProxyOptions } 564 | end 565 | end 566 | end 567 | -------------------------------------------------------------------------------- /spec/kintone/query_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | require 'kintone/query' 3 | 4 | describe Kintone::Query do 5 | describe '#to_s' do 6 | subject { target.to_s } 7 | 8 | context '==', 'with field' do 9 | where(:target, :result) do 10 | [ 11 | [Kintone::Query.new { field(:text) == '"Hello, world."' }, 'text = "Hello, world."'], 12 | [Kintone::Query.new { field(:text) == 'Hello, world.' }, 'text = "Hello, world."'], 13 | [Kintone::Query.new { field('作成日時') == now }, '作成日時 = NOW()'], 14 | [Kintone::Query.new { field('作成日時') == today }, '作成日時 = TODAY()'], 15 | [Kintone::Query.new { field('作成日時') == this_month }, '作成日時 = THIS_MONTH()'], 16 | [Kintone::Query.new { field('作成日時') == last_month }, '作成日時 = LAST_MONTH()'], 17 | [Kintone::Query.new { field('作成日時') == this_year }, '作成日時 = THIS_YEAR()'], 18 | [Kintone::Query.new { field(:number) == 100 }, 'number = 100'] 19 | ] 20 | end 21 | 22 | with_them do 23 | it { expect(subject).to eq result } 24 | end 25 | end 26 | 27 | context '==', 'with f' do 28 | where(:target, :result) do 29 | [ 30 | [Kintone::Query.new { f(:text) == '"Hello, world."' }, 'text = "Hello, world."'], 31 | [Kintone::Query.new { f(:text) == 'Hello, world.' }, 'text = "Hello, world."'], 32 | [Kintone::Query.new { f('作成日時') == now }, '作成日時 = NOW()'], 33 | [Kintone::Query.new { f('作成日時') == today }, '作成日時 = TODAY()'], 34 | [Kintone::Query.new { f('作成日時') == this_month }, '作成日時 = THIS_MONTH()'], 35 | [Kintone::Query.new { f('作成日時') == last_month }, '作成日時 = LAST_MONTH()'], 36 | [Kintone::Query.new { f('作成日時') == this_year }, '作成日時 = THIS_YEAR()'], 37 | [Kintone::Query.new { f(:number) == 100 }, 'number = 100'] 38 | ] 39 | end 40 | 41 | with_them do 42 | it { expect(subject).to eq result } 43 | end 44 | end 45 | 46 | context '!=', 'with field' do 47 | where(:target, :result) do 48 | [ 49 | [Kintone::Query.new { field(:text) != '"Hello, world."' }, 'text != "Hello, world."'], 50 | [Kintone::Query.new { field(:text) != 'Hello, world.' }, 'text != "Hello, world."'], 51 | [Kintone::Query.new { field('作成日時') != now }, '作成日時 != NOW()'], 52 | [Kintone::Query.new { field('作成日時') != today }, '作成日時 != TODAY()'], 53 | [Kintone::Query.new { field('作成日時') != this_month }, '作成日時 != THIS_MONTH()'], 54 | [Kintone::Query.new { field('作成日時') != last_month }, '作成日時 != LAST_MONTH()'], 55 | [Kintone::Query.new { field('作成日時') != this_year }, '作成日時 != THIS_YEAR()'], 56 | [Kintone::Query.new { field(:number) != 100 }, 'number != 100'] 57 | ] 58 | end 59 | 60 | with_them do 61 | it { expect(subject).to eq result } 62 | end 63 | end 64 | 65 | context '!=', 'with f' do 66 | where(:target, :result) do 67 | [ 68 | [Kintone::Query.new { f(:text) != '"Hello, world."' }, 'text != "Hello, world."'], 69 | [Kintone::Query.new { f(:text) != 'Hello, world.' }, 'text != "Hello, world."'], 70 | [Kintone::Query.new { f('作成日時') != now }, '作成日時 != NOW()'], 71 | [Kintone::Query.new { f('作成日時') != today }, '作成日時 != TODAY()'], 72 | [Kintone::Query.new { f('作成日時') != this_month }, '作成日時 != THIS_MONTH()'], 73 | [Kintone::Query.new { f('作成日時') != last_month }, '作成日時 != LAST_MONTH()'], 74 | [Kintone::Query.new { f('作成日時') != this_year }, '作成日時 != THIS_YEAR()'], 75 | [Kintone::Query.new { f(:number) != 100 }, 'number != 100'] 76 | ] 77 | end 78 | 79 | with_them do 80 | it { expect(subject).to eq result } 81 | end 82 | end 83 | 84 | context '>', 'with field' do 85 | where(:target, :result) do 86 | [ 87 | [Kintone::Query.new { field(:text) > '"Hello, world."' }, 'text > "Hello, world."'], 88 | [Kintone::Query.new { field(:text) > 'Hello, world.' }, 'text > "Hello, world."'], 89 | [Kintone::Query.new { field('作成日時') > now }, '作成日時 > NOW()'], 90 | [Kintone::Query.new { field('作成日時') > today }, '作成日時 > TODAY()'], 91 | [Kintone::Query.new { field('作成日時') > this_month }, '作成日時 > THIS_MONTH()'], 92 | [Kintone::Query.new { field('作成日時') > last_month }, '作成日時 > LAST_MONTH()'], 93 | [Kintone::Query.new { field('作成日時') > this_year }, '作成日時 > THIS_YEAR()'], 94 | [Kintone::Query.new { field(:number) > 100 }, 'number > 100'] 95 | ] 96 | end 97 | 98 | with_them do 99 | it { expect(subject).to eq result } 100 | end 101 | end 102 | 103 | context '>', 'with f' do 104 | where(:target, :result) do 105 | [ 106 | [Kintone::Query.new { f(:text) > '"Hello, world."' }, 'text > "Hello, world."'], 107 | [Kintone::Query.new { f(:text) > 'Hello, world.' }, 'text > "Hello, world."'], 108 | [Kintone::Query.new { f('作成日時') > now }, '作成日時 > NOW()'], 109 | [Kintone::Query.new { f('作成日時') > today }, '作成日時 > TODAY()'], 110 | [Kintone::Query.new { f('作成日時') > this_month }, '作成日時 > THIS_MONTH()'], 111 | [Kintone::Query.new { f('作成日時') > last_month }, '作成日時 > LAST_MONTH()'], 112 | [Kintone::Query.new { f('作成日時') > this_year }, '作成日時 > THIS_YEAR()'], 113 | [Kintone::Query.new { f(:number) > 100 }, 'number > 100'] 114 | ] 115 | end 116 | 117 | with_them do 118 | it { expect(subject).to eq result } 119 | end 120 | end 121 | 122 | context '<', 'with field' do 123 | where(:target, :result) do 124 | [ 125 | [Kintone::Query.new { field(:text) < '"Hello, world."' }, 'text < "Hello, world."'], 126 | [Kintone::Query.new { field(:text) < 'Hello, world.' }, 'text < "Hello, world."'], 127 | [Kintone::Query.new { field('作成日時') < now }, '作成日時 < NOW()'], 128 | [Kintone::Query.new { field('作成日時') < today }, '作成日時 < TODAY()'], 129 | [Kintone::Query.new { field('作成日時') < this_month }, '作成日時 < THIS_MONTH()'], 130 | [Kintone::Query.new { field('作成日時') < last_month }, '作成日時 < LAST_MONTH()'], 131 | [Kintone::Query.new { field('作成日時') < this_year }, '作成日時 < THIS_YEAR()'], 132 | [Kintone::Query.new { field(:number) < 100 }, 'number < 100'] 133 | ] 134 | end 135 | 136 | with_them do 137 | it { expect(subject).to eq result } 138 | end 139 | end 140 | 141 | context '<', 'with f' do 142 | where(:target, :result) do 143 | [ 144 | [Kintone::Query.new { f(:text) < '"Hello, world."' }, 'text < "Hello, world."'], 145 | [Kintone::Query.new { f(:text) < 'Hello, world.' }, 'text < "Hello, world."'], 146 | [Kintone::Query.new { f('作成日時') < now }, '作成日時 < NOW()'], 147 | [Kintone::Query.new { f('作成日時') < today }, '作成日時 < TODAY()'], 148 | [Kintone::Query.new { f('作成日時') < this_month }, '作成日時 < THIS_MONTH()'], 149 | [Kintone::Query.new { f('作成日時') < last_month }, '作成日時 < LAST_MONTH()'], 150 | [Kintone::Query.new { f('作成日時') < this_year }, '作成日時 < THIS_YEAR()'], 151 | [Kintone::Query.new { f(:number) < 100 }, 'number < 100'] 152 | ] 153 | end 154 | 155 | with_them do 156 | it { expect(subject).to eq result } 157 | end 158 | end 159 | 160 | context '>=', 'with field' do 161 | where(:target, :result) do 162 | [ 163 | [Kintone::Query.new { field(:text) >= '"Hello, world."' }, 'text >= "Hello, world."'], 164 | [Kintone::Query.new { field(:text) >= 'Hello, world.' }, 'text >= "Hello, world."'], 165 | [Kintone::Query.new { field('作成日時') >= now }, '作成日時 >= NOW()'], 166 | [Kintone::Query.new { field('作成日時') >= today }, '作成日時 >= TODAY()'], 167 | [Kintone::Query.new { field('作成日時') >= this_month }, '作成日時 >= THIS_MONTH()'], 168 | [Kintone::Query.new { field('作成日時') >= last_month }, '作成日時 >= LAST_MONTH()'], 169 | [Kintone::Query.new { field('作成日時') >= this_year }, '作成日時 >= THIS_YEAR()'], 170 | [Kintone::Query.new { field(:number) >= 100 }, 'number >= 100'] 171 | ] 172 | end 173 | 174 | with_them do 175 | it { expect(subject).to eq result } 176 | end 177 | end 178 | 179 | context '>=', 'with f' do 180 | where(:target, :result) do 181 | [ 182 | [Kintone::Query.new { f(:text) >= '"Hello, world."' }, 'text >= "Hello, world."'], 183 | [Kintone::Query.new { f(:text) >= 'Hello, world.' }, 'text >= "Hello, world."'], 184 | [Kintone::Query.new { f('作成日時') >= now }, '作成日時 >= NOW()'], 185 | [Kintone::Query.new { f('作成日時') >= today }, '作成日時 >= TODAY()'], 186 | [Kintone::Query.new { f('作成日時') >= this_month }, '作成日時 >= THIS_MONTH()'], 187 | [Kintone::Query.new { f('作成日時') >= last_month }, '作成日時 >= LAST_MONTH()'], 188 | [Kintone::Query.new { f('作成日時') >= this_year }, '作成日時 >= THIS_YEAR()'], 189 | [Kintone::Query.new { f(:number) >= 100 }, 'number >= 100'] 190 | ] 191 | end 192 | 193 | with_them do 194 | it { expect(subject).to eq result } 195 | end 196 | end 197 | 198 | context '<=', 'with field' do 199 | where(:target, :result) do 200 | [ 201 | [Kintone::Query.new { field(:text) <= '"Hello, world."' }, 'text <= "Hello, world."'], 202 | [Kintone::Query.new { field(:text) <= 'Hello, world.' }, 'text <= "Hello, world."'], 203 | [Kintone::Query.new { field('作成日時') <= now }, '作成日時 <= NOW()'], 204 | [Kintone::Query.new { field('作成日時') <= today }, '作成日時 <= TODAY()'], 205 | [Kintone::Query.new { field('作成日時') <= this_month }, '作成日時 <= THIS_MONTH()'], 206 | [Kintone::Query.new { field('作成日時') <= last_month }, '作成日時 <= LAST_MONTH()'], 207 | [Kintone::Query.new { field('作成日時') <= this_year }, '作成日時 <= THIS_YEAR()'], 208 | [Kintone::Query.new { field(:number) <= 100 }, 'number <= 100'] 209 | ] 210 | end 211 | 212 | with_them do 213 | it { expect(subject).to eq result } 214 | end 215 | end 216 | 217 | context '<=', 'with f' do 218 | where(:target, :result) do 219 | [ 220 | [Kintone::Query.new { f(:text) <= '"Hello, world."' }, 'text <= "Hello, world."'], 221 | [Kintone::Query.new { f(:text) <= 'Hello, world.' }, 'text <= "Hello, world."'], 222 | [Kintone::Query.new { f('作成日時') <= now }, '作成日時 <= NOW()'], 223 | [Kintone::Query.new { f('作成日時') <= today }, '作成日時 <= TODAY()'], 224 | [Kintone::Query.new { f('作成日時') <= this_month }, '作成日時 <= THIS_MONTH()'], 225 | [Kintone::Query.new { f('作成日時') <= last_month }, '作成日時 <= LAST_MONTH()'], 226 | [Kintone::Query.new { f('作成日時') <= this_year }, '作成日時 <= THIS_YEAR()'], 227 | [Kintone::Query.new { f(:number) <= 100 }, 'number <= 100'] 228 | ] 229 | end 230 | 231 | with_them do 232 | it { expect(subject).to eq result } 233 | end 234 | end 235 | 236 | context 'in', 'with field' do 237 | where(:target, :result) do 238 | [ 239 | [Kintone::Query.new { field(:dropdown).in(['"A"', '"B"']) }, 'dropdown in ("A", "B")'], 240 | [Kintone::Query.new { field(:dropdown).in(%w(A B)) }, 'dropdown in ("A", "B")'], 241 | [Kintone::Query.new { field(:dropdown).in([:A, :B]) }, 'dropdown in ("A", "B")'], 242 | [Kintone::Query.new { field(:dropdown).in([100, 200]) }, 'dropdown in (100, 200)'], 243 | [Kintone::Query.new { field('作成者').in([login_user]) }, '作成者 in (LOGINUSER())'] 244 | ] 245 | end 246 | 247 | with_them do 248 | it { expect(subject).to eq result } 249 | end 250 | end 251 | 252 | context 'in', 'with f' do 253 | where(:target, :result) do 254 | [ 255 | [ 256 | Kintone::Query.new { f(:dropdown).in(['"A"', '"B"']) }, 257 | 'dropdown in ("A", "B")' 258 | ], 259 | [ 260 | Kintone::Query.new { f(:dropdown).in(%w(A B)) }, 261 | 'dropdown in ("A", "B")' 262 | ], 263 | [ 264 | Kintone::Query.new { f(:dropdown).in([:A, :B]) }, 265 | 'dropdown in ("A", "B")' 266 | ], 267 | [ 268 | Kintone::Query.new { f(:dropdown).in([100, 200]) }, 269 | 'dropdown in (100, 200)' 270 | ], 271 | [ 272 | Kintone::Query.new { f('作成者').in([login_user]) }, 273 | '作成者 in (LOGINUSER())' 274 | ], 275 | [ 276 | Kintone::Query.new { field('組織').in([primary_organization]) }, 277 | '組織 in (PRIMARY_ORGANIZATION())' 278 | ] 279 | ] 280 | end 281 | 282 | with_them do 283 | it { expect(subject).to eq result } 284 | end 285 | end 286 | 287 | context 'not in', 'with field' do 288 | where(:target, :result) do 289 | [ 290 | [ 291 | Kintone::Query.new { field(:dropdown).not_in(['"A"', '"B"']) }, 292 | 'dropdown not in ("A", "B")' 293 | ], 294 | [ 295 | Kintone::Query.new { field(:dropdown).not_in(%w(A B)) }, 296 | 'dropdown not in ("A", "B")' 297 | ], 298 | [ 299 | Kintone::Query.new { field(:dropdown).not_in([:A, :B]) }, 300 | 'dropdown not in ("A", "B")' 301 | ], 302 | [ 303 | Kintone::Query.new { field(:dropdown).not_in([100, 200]) }, 304 | 'dropdown not in (100, 200)' 305 | ], 306 | [ 307 | Kintone::Query.new { field('作成者').not_in([login_user]) }, 308 | '作成者 not in (LOGINUSER())' 309 | ], 310 | [ 311 | Kintone::Query.new { field('組織').not_in([primary_organization]) }, 312 | '組織 not in (PRIMARY_ORGANIZATION())' 313 | ] 314 | ] 315 | end 316 | 317 | with_them do 318 | it { expect(subject).to eq result } 319 | end 320 | end 321 | 322 | context 'not in', 'with field' do 323 | where(:target, :result) do 324 | [ 325 | [ 326 | Kintone::Query.new { f(:dropdown).not_in(['"A"', '"B"']) }, 327 | 'dropdown not in ("A", "B")' 328 | ], 329 | [ 330 | Kintone::Query.new { f(:dropdown).not_in(%w(A B)) }, 331 | 'dropdown not in ("A", "B")' 332 | ], 333 | [ 334 | Kintone::Query.new { f(:dropdown).not_in([:A, :B]) }, 335 | 'dropdown not in ("A", "B")' 336 | ], 337 | [ 338 | Kintone::Query.new { f(:dropdown).not_in([100, 200]) }, 339 | 'dropdown not in (100, 200)' 340 | ], 341 | [ 342 | Kintone::Query.new { f('作成者').not_in([login_user]) }, 343 | '作成者 not in (LOGINUSER())' 344 | ] 345 | ] 346 | end 347 | 348 | with_them do 349 | it { expect(subject).to eq result } 350 | end 351 | end 352 | 353 | context 'like', 'with field' do 354 | where(:target, :result) do 355 | [ 356 | [Kintone::Query.new { field(:text).like('Hello') }, 'text like "Hello"'], 357 | [Kintone::Query.new { field(:text).like('"Hello"') }, 'text like "Hello"'], 358 | [Kintone::Query.new { field(:text).like(:Hello) }, 'text like "Hello"'] 359 | ] 360 | end 361 | 362 | with_them do 363 | it { expect(subject).to eq result } 364 | end 365 | end 366 | 367 | context 'like', 'with f' do 368 | where(:target, :result) do 369 | [ 370 | [Kintone::Query.new { f(:text).like('Hello') }, 'text like "Hello"'], 371 | [Kintone::Query.new { f(:text).like('"Hello"') }, 'text like "Hello"'], 372 | [Kintone::Query.new { f(:text).like(:Hello) }, 'text like "Hello"'] 373 | ] 374 | end 375 | 376 | with_them do 377 | it { expect(subject).to eq result } 378 | end 379 | end 380 | 381 | context 'not like', 'with field' do 382 | where(:target, :result) do 383 | [ 384 | [Kintone::Query.new { field(:text).not_like('Hello') }, 'text not like "Hello"'], 385 | [Kintone::Query.new { field(:text).not_like('"Hello"') }, 'text not like "Hello"'], 386 | [Kintone::Query.new { field(:text).not_like(:Hello) }, 'text not like "Hello"'] 387 | ] 388 | end 389 | 390 | with_them do 391 | it { expect(subject).to eq result } 392 | end 393 | end 394 | 395 | context 'not like', 'with f' do 396 | where(:target, :result) do 397 | [ 398 | [Kintone::Query.new { f(:text).not_like('Hello') }, 'text not like "Hello"'], 399 | [Kintone::Query.new { f(:text).not_like('"Hello"') }, 'text not like "Hello"'], 400 | [Kintone::Query.new { f(:text).not_like(:Hello) }, 'text not like "Hello"'] 401 | ] 402 | end 403 | 404 | with_them do 405 | it { expect(subject).to eq result } 406 | end 407 | end 408 | 409 | context 'and!' do 410 | let(:target) do 411 | Kintone::Query.new do 412 | field(:text).like 'Hello' 413 | and! 414 | field(:number) > 100 415 | end 416 | end 417 | 418 | def result 419 | 'text like "Hello" and number > 100' 420 | end 421 | 422 | it { expect(subject).to eq result } 423 | end 424 | 425 | context 'or!' do 426 | let(:target) do 427 | Kintone::Query.new do 428 | field(:text).like 'Hello' 429 | or! 430 | field(:number) > 100 431 | end 432 | end 433 | 434 | def result 435 | 'text like "Hello" or number > 100' 436 | end 437 | 438 | it { expect(subject).to eq result } 439 | end 440 | 441 | context 'precede' do 442 | let(:target) do 443 | Kintone::Query.new do 444 | precede do 445 | field(:text).like 'Hello' 446 | or! 447 | field(:number) > 100 448 | end 449 | and! 450 | precede do 451 | field(:text2).not_like 'Hello' 452 | and! 453 | field(:number2) <= 100 454 | end 455 | end 456 | end 457 | 458 | def result 459 | '(text like "Hello" or number > 100) and (text2 not like "Hello" and number2 <= 100)' 460 | end 461 | 462 | it { expect(subject).to eq result } 463 | end 464 | 465 | context 'order by' do 466 | where(:target, :result) do 467 | [ 468 | [Kintone::Query.new { order_by(:record_id, :asc) }, 'order by record_id asc'], 469 | [Kintone::Query.new { order_by(:record_id, :desc) }, 'order by record_id desc'], 470 | [Kintone::Query.new { order_by(:record_id) }, 'order by record_id asc'], 471 | [Kintone::Query.new { order_by('作成日時', :desc) }, 'order by 作成日時 desc'] 472 | ] 473 | end 474 | 475 | with_them do 476 | it { expect(subject).to eq result } 477 | end 478 | end 479 | 480 | context 'limit' do 481 | where(:target, :result) do 482 | [ 483 | [Kintone::Query.new { limit(20) }, 'limit 20'], 484 | [Kintone::Query.new { limit('20') }, 'limit 20'] 485 | ] 486 | end 487 | 488 | with_them do 489 | it { expect(subject).to eq result } 490 | end 491 | end 492 | 493 | context 'offset' do 494 | where(:target, :result) do 495 | [ 496 | [Kintone::Query.new { offset(30) }, 'offset 30'], 497 | [Kintone::Query.new { offset('30') }, 'offset 30'] 498 | ] 499 | end 500 | 501 | with_them do 502 | it { expect(subject).to eq result } 503 | end 504 | end 505 | end 506 | end 507 | --------------------------------------------------------------------------------