From 05aa48e70a67ee256b819f11b37623628cd67983 Mon Sep 17 00:00:00 2001 From: Enrico Stano Date: Thu, 21 Feb 2019 22:43:07 +0100 Subject: [PATCH 1/8] Add pg_search gem --- Gemfile | 1 + Gemfile.lock | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/Gemfile b/Gemfile index e034724ba..497d90e7a 100644 --- a/Gemfile +++ b/Gemfile @@ -18,6 +18,7 @@ gem 'kaminari', '~> 1.1.1' gem "simple_form", ">= 3.0.0" gem 'rollbar', '2.8.3' gem 'whenever', require: false +gem 'pg_search', '2.1.4' gem 'prawn', '~> 2.2.0' gem 'prawn-table', '~> 0.2.2' gem 'elasticsearch-model' diff --git a/Gemfile.lock b/Gemfile.lock index 1a521d77c..c93320b97 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -223,6 +223,9 @@ GEM ast (~> 2.4.0) pdf-core (0.7.0) pg (0.17.1) + pg_search (2.1.4) + activerecord (>= 4.2) + activesupport (>= 4.2) polyamorous (1.3.3) activerecord (>= 3.0) powerpack (0.1.1) @@ -424,6 +427,7 @@ DEPENDENCIES letter_opener (= 1.4.1) localeapp (= 2.1.1) pg (= 0.17.1) + pg_search (= 2.1.4) prawn (~> 2.2.0) prawn-table (~> 0.2.2) pundit (~> 2.0.0) From 0af66cdfe786477e72eb4e87b1c67116708345b3 Mon Sep 17 00:00:00 2001 From: Enrico Stano Date: Thu, 21 Feb 2019 22:43:50 +0100 Subject: [PATCH 2/8] Upgrade bundler --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index c93320b97..6f524d157 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -457,4 +457,4 @@ RUBY VERSION ruby 2.3.0p0 BUNDLED WITH - 1.16.2 + 1.17.0 From 6fd92f192a5479808ec1ceeb6d71824dade2c83e Mon Sep 17 00:00:00 2001 From: Enrico Stano Date: Thu, 21 Feb 2019 22:51:42 +0100 Subject: [PATCH 3/8] Remove elasticsearch and use pg_search --- .travis.yml | 4 -- Gemfile | 2 - Gemfile.lock | 17 ------ app/controllers/members_controller.rb | 5 -- app/controllers/posts_controller.rb | 39 ++++++-------- app/models/member.rb | 12 ----- app/models/post.rb | 62 ++-------------------- config/initializers/elasticsearch.rb | 3 -- lib/tasks/elasticsearch.rake | 1 - spec/controllers/offers_controller_spec.rb | 12 ----- 10 files changed, 19 insertions(+), 138 deletions(-) delete mode 100644 config/initializers/elasticsearch.rb delete mode 100644 lib/tasks/elasticsearch.rake diff --git a/.travis.yml b/.travis.yml index 730632329..95c06230b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,11 +10,7 @@ before_script: - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter - chmod +x ./cc-test-reporter - ./cc-test-reporter before-build - # allow elasticsearch to be ready - https://docs.travis-ci.com/user/database-setup/#ElasticSearch - - sleep 10 after_script: - ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT -services: - - elasticsearch addons: chrome: stable diff --git a/Gemfile b/Gemfile index 497d90e7a..09cc1803f 100644 --- a/Gemfile +++ b/Gemfile @@ -21,8 +21,6 @@ gem 'whenever', require: false gem 'pg_search', '2.1.4' gem 'prawn', '~> 2.2.0' gem 'prawn-table', '~> 0.2.2' -gem 'elasticsearch-model' -gem 'elasticsearch-rails' gem 'skylight' gem 'sidekiq', '5.1.3' gem 'sidekiq-cron', '0.6.3' diff --git a/Gemfile.lock b/Gemfile.lock index 6f524d157..a511eea11 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -124,19 +124,6 @@ GEM dotenv-rails (2.7.1) dotenv (= 2.7.1) railties (>= 3.2, < 6.1) - elasticsearch (1.0.8) - elasticsearch-api (= 1.0.7) - elasticsearch-transport (= 1.0.7) - elasticsearch-api (1.0.7) - multi_json - elasticsearch-model (0.1.7) - activesupport (> 3) - elasticsearch (> 0.4) - hashie - elasticsearch-rails (0.1.7) - elasticsearch-transport (1.0.7) - faraday - multi_json erubi (1.7.1) erubis (2.7.0) et-orbi (1.1.2) @@ -157,7 +144,6 @@ GEM has_scope (0.6.0) actionpack (>= 3.2, < 5) activesupport (>= 3.2, < 5) - hashie (3.4.1) hstore_translate (1.0.0) activerecord (>= 3.1.0) http-cookie (1.0.3) @@ -209,7 +195,6 @@ GEM mini_portile2 (2.3.0) minitest (5.11.3) multi_json (1.11.2) - multipart-post (2.0.0) net-scp (1.2.1) net-ssh (>= 2.6.5) net-ssh (2.9.2) @@ -415,8 +400,6 @@ DEPENDENCIES database_cleaner (= 1.6.2) devise (~> 4.5.0) dotenv-rails (~> 2.7.1) - elasticsearch-model - elasticsearch-rails fabrication faker (~> 1.9) has_scope diff --git a/app/controllers/members_controller.rb b/app/controllers/members_controller.rb index 5545f4186..d8dff153d 100644 --- a/app/controllers/members_controller.rb +++ b/app/controllers/members_controller.rb @@ -20,11 +20,6 @@ def toggle_manager def toggle_active find_member @member.toggle(:active).save! - if @member.active - @member.add_all_posts_to_index - else - @member.remove_all_posts_from_index - end respond_to do |format| format.json { head :ok } format.html { redirect_to :back } diff --git a/app/controllers/posts_controller.rb b/app/controllers/posts_controller.rb index a74db794b..55fe2d32e 100644 --- a/app/controllers/posts_controller.rb +++ b/app/controllers/posts_controller.rb @@ -4,31 +4,22 @@ class PostsController < ApplicationController has_scope :by_organization, as: :org def index - if (query = params[:q]).present? - # match query term on fields - must = [ { multi_match: { - query: query.to_s, - type: "phrase_prefix", - fields: ["title^2", "description", "tags^2"] - } } ] - if current_organization.present? - # filter by organization - must << { term: { organization_id: { value: current_organization.id } } } - end - posts = model.__elasticsearch__.search( - query: { - bool: { - must: must - } - } - ).page(params[:page]).per(25).records - else - posts = model.active.of_active_members - if current_organization.present? - posts = posts.merge(current_organization.posts) - end - posts = apply_scopes(posts).page(params[:page]).per(25) + context = model.active.of_active_members + if current_organization.present? + context = context.where( + organization_id: current_organization.id + ) end + + posts = if (query = params[:q]).present? + context. + search_by_query(query). + page(params[:page]). + per(25) + else + apply_scopes(context).page(params[:page]).per(25) + end + instance_variable_set("@#{resources}", posts) end diff --git a/app/models/member.rb b/app/models/member.rb index 6e5381860..47739daa0 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -44,18 +44,6 @@ def display_id member_uid end - def remove_all_posts_from_index - Post.with_member.where("members.id = ?", self.id).find_each do |post| - post.delete_document - end - end - - def add_all_posts_to_index - Post.with_member.where("members.id = ?", self.id).find_each do |post| - post.update_or_delete_document(self) - end - end - def assign_registration_number self.member_uid ||= organization.next_reg_number_seq end diff --git a/app/models/post.rb b/app/models/post.rb index 485f0f319..85f0c02e3 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -1,40 +1,10 @@ -require 'elasticsearch/model' - class Post < ActiveRecord::Base include Taggable + include PgSearch - # Elasticsearch::Model doesn't work well with STI, so - # include it in subclasses directly. - def self.inherited(child) - super - - child.instance_eval do - include Elasticsearch::Model - - after_commit :index_document, on: :create - after_commit :update_or_delete_document, on: :update - after_commit :delete_document, on: :destroy - - settings( - analysis: { - analyzer: { - normal: { - tokenizer: "standard", - # lowercase, unaccent - filter: %w[lowercase asciifolding] - } - } - } - ) do - mapping do - indexes :title, analyzer: "normal" - indexes :description, analyzer: "normal" - indexes :tags - indexes :organization_id, type: :integer - end - end - end - end + pg_search_scope :search_by_query, + :against => [:title, :description, :tags], + :ignoring => :accents attr_reader :member_id @@ -72,30 +42,6 @@ def self.inherited(child) validates :category, presence: true validates :title, presence: true - def index_document - __elasticsearch__.index_document - end - - # pass member when doing bulk things - def update_or_delete_document(member = nil) - member ||= self.member - if active && member.try(:active) - begin - __elasticsearch__.update_document - rescue # document was not in the index. TODO: more specifi exception class - __elasticsearch__.index_document - end - else - __elasticsearch__.delete_document - end - rescue # document was not in the index. TODO: more specifi exception class - end - - def delete_document - __elasticsearch__.delete_document - rescue # document was not in the index. TODO: more specifi exception class - end - def as_indexed_json(*) as_json(only: [:title, :description, :tags, :organization_id]) end diff --git a/config/initializers/elasticsearch.rb b/config/initializers/elasticsearch.rb deleted file mode 100644 index 4f8d88b9e..000000000 --- a/config/initializers/elasticsearch.rb +++ /dev/null @@ -1,3 +0,0 @@ -if ENV["ELASTICSEARCH_URL"].present? - Elasticsearch::Model.client = Elasticsearch::Client.new host: ENV["ELASTICSEARCH_URL"] -end diff --git a/lib/tasks/elasticsearch.rake b/lib/tasks/elasticsearch.rake deleted file mode 100644 index 744fd91a7..000000000 --- a/lib/tasks/elasticsearch.rake +++ /dev/null @@ -1 +0,0 @@ -require 'elasticsearch/rails/tasks/import' diff --git a/spec/controllers/offers_controller_spec.rb b/spec/controllers/offers_controller_spec.rb index 4f1db8ecf..3757f1fa7 100644 --- a/spec/controllers/offers_controller_spec.rb +++ b/spec/controllers/offers_controller_spec.rb @@ -36,23 +36,11 @@ end describe "GET #index (search)" do - before do - Offer.__elasticsearch__.create_index!(force: true) - - # Import any already existing model into the index - # for instance the ones that have been created in upper - # `let!` or `before` blocks - Offer.__elasticsearch__.import(force: true, refresh: true) - end - it "populates an array of offers" do login(another_member.user) get "index", q: offer.title.split(/\s/).first - # @offers is a wrapper from Elasticsearch. It's iterator-equivalent to - # the underlying query from the database. - expect(assigns(:offers)).to be_a Elasticsearch::Model::Response::Records expect(assigns(:offers).size).to eq 1 expect(assigns(:offers)[0]).to eq offer expect(assigns(:offers).to_a).to eq([offer]) From 8d8b2be48b79448853eb743de03ac367a712680e Mon Sep 17 00:00:00 2001 From: Marc Anguera Insa Date: Thu, 7 Mar 2019 23:29:47 +0100 Subject: [PATCH 4/8] Enable partial word searches in pg_search Doc: https://github.com/Casecommons/pg_search#prefix-postgresql-84-and-newer-only --- app/models/post.rb | 7 +++++-- spec/controllers/offers_controller_spec.rb | 10 ++++++++-- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/app/models/post.rb b/app/models/post.rb index 85f0c02e3..644ab6164 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -3,8 +3,11 @@ class Post < ActiveRecord::Base include PgSearch pg_search_scope :search_by_query, - :against => [:title, :description, :tags], - :ignoring => :accents + against: [:title, :description, :tags], + ignoring: :accents, + using: { + tsearch: { prefix: true } + } attr_reader :member_id diff --git a/spec/controllers/offers_controller_spec.rb b/spec/controllers/offers_controller_spec.rb index 3757f1fa7..cca4c262c 100644 --- a/spec/controllers/offers_controller_spec.rb +++ b/spec/controllers/offers_controller_spec.rb @@ -36,15 +36,21 @@ end describe "GET #index (search)" do - it "populates an array of offers" do - login(another_member.user) + before { login(another_member.user) } + it "populates an array of offers" do get "index", q: offer.title.split(/\s/).first expect(assigns(:offers).size).to eq 1 expect(assigns(:offers)[0]).to eq offer expect(assigns(:offers).to_a).to eq([offer]) end + + it "allows to search by partial word" do + get :index, q: offer.title.split(/\s/).first[0..-2] + + expect(assigns(:offers)).to include offer + end end describe 'GET #show' do From aab779c2ca2337476ffbe0029b391b660beebe40 Mon Sep 17 00:00:00 2001 From: Enrico Stano Date: Fri, 24 May 2019 00:58:42 +0200 Subject: [PATCH 5/8] Add tsvector column, trigger, index and unaccent extension --- app/models/post.rb | 5 ++- ...90523213421_add_tsvector_column_to_post.rb | 32 +++++++++++++++++++ ...0190523225323_enable_unaccent_extension.rb | 9 ++++++ db/schema.rb | 5 ++- 4 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 db/migrate/20190523213421_add_tsvector_column_to_post.rb create mode 100644 db/migrate/20190523225323_enable_unaccent_extension.rb diff --git a/app/models/post.rb b/app/models/post.rb index 644ab6164..54711fef9 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -6,7 +6,10 @@ class Post < ActiveRecord::Base against: [:title, :description, :tags], ignoring: :accents, using: { - tsearch: { prefix: true } + tsearch: { + prefix: true, + tsvector_column: 'tsv' + } } attr_reader :member_id diff --git a/db/migrate/20190523213421_add_tsvector_column_to_post.rb b/db/migrate/20190523213421_add_tsvector_column_to_post.rb new file mode 100644 index 000000000..fe124d235 --- /dev/null +++ b/db/migrate/20190523213421_add_tsvector_column_to_post.rb @@ -0,0 +1,32 @@ +class AddTsvectorColumnToPost < ActiveRecord::Migration + def up + execute <<-SQL + ALTER TABLE posts ADD COLUMN tsv tsvector; + + CREATE FUNCTION posts_trigger() RETURNS trigger AS $$ + begin + new.tsv := + to_tsvector('simple', unaccent(coalesce(new.title::text, ''))) || + to_tsvector('simple', unaccent(coalesce(new.description::text, ''))) || + to_tsvector('simple', unaccent(coalesce(new.tags::text, ''))); + return new; + end + $$ LANGUAGE plpgsql; + + CREATE TRIGGER tsvectorupdate BEFORE INSERT OR UPDATE + ON posts FOR EACH ROW EXECUTE PROCEDURE posts_trigger(); + SQL + + add_index :posts, :tsv, using: "gin" + end + + def down + execute <<-SQL + DROP TRIGGER tsvectorupdate ON posts; + DROP FUNCTION posts_trigger(); + SQL + + remove_index :posts, :tsv + remove_column :posts, :tsv + end +end diff --git a/db/migrate/20190523225323_enable_unaccent_extension.rb b/db/migrate/20190523225323_enable_unaccent_extension.rb new file mode 100644 index 000000000..d5dcc420f --- /dev/null +++ b/db/migrate/20190523225323_enable_unaccent_extension.rb @@ -0,0 +1,9 @@ +class EnableUnaccentExtension < ActiveRecord::Migration + def up + enable_extension "unaccent" + end + + def down + disable_extension "unaccent" + end +end diff --git a/db/schema.rb b/db/schema.rb index bfcd9e381..3adbc2d2f 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,12 +11,13 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20190412163011) do +ActiveRecord::Schema.define(version: 20190523225323) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" enable_extension "hstore" enable_extension "pg_trgm" + enable_extension "unaccent" create_table "accounts", force: :cascade do |t| t.integer "accountable_id" @@ -147,11 +148,13 @@ t.integer "organization_id" t.boolean "active", default: true t.boolean "is_group", default: false + t.tsvector "tsv" end add_index "posts", ["category_id"], name: "index_posts_on_category_id", using: :btree add_index "posts", ["organization_id"], name: "index_posts_on_organization_id", using: :btree add_index "posts", ["tags"], name: "index_posts_on_tags", using: :gin + add_index "posts", ["tsv"], name: "index_posts_on_tsv", using: :gin add_index "posts", ["user_id"], name: "index_posts_on_user_id", using: :btree create_table "push_notifications", force: :cascade do |t| From 3b4a65631a83103c85fb7b141753b4043c065ed3 Mon Sep 17 00:00:00 2001 From: Enrico Stano Date: Fri, 24 May 2019 17:18:44 +0200 Subject: [PATCH 6/8] Damn conflicts! --- Gemfile.lock | 2 -- 1 file changed, 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index a511eea11..173fbbb20 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -132,8 +132,6 @@ GEM fabrication (2.11.3) faker (1.9.3) i18n (>= 0.7) - faraday (0.9.1) - multipart-post (>= 1.2, < 3) ffi (1.10.0) formtastic (3.1.5) actionpack (>= 3.2.13) From e09469ce1aae16b0728fdeb3c3f86ecbdd61217d Mon Sep 17 00:00:00 2001 From: Enrico Stano Date: Fri, 24 May 2019 18:19:21 +0200 Subject: [PATCH 7/8] Use SQL for schema instead of Ruby --- config/application.rb | 4 + db/schema.rb | 226 -------- db/structure.sql | 1141 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 1145 insertions(+), 226 deletions(-) delete mode 100644 db/schema.rb create mode 100644 db/structure.sql diff --git a/config/application.rb b/config/application.rb index 4bba4fc1b..4edfc6c1d 100644 --- a/config/application.rb +++ b/config/application.rb @@ -35,5 +35,9 @@ class Application < Rails::Application # ActiveJob configuration config.active_job.queue_adapter = :sidekiq + + # Use db/structure.sql with SQL as schema format + # This is needed to store in the schema SQL statements not covered by the ORM + config.active_record.schema_format = :sql end end diff --git a/db/schema.rb b/db/schema.rb deleted file mode 100644 index 3adbc2d2f..000000000 --- a/db/schema.rb +++ /dev/null @@ -1,226 +0,0 @@ -# encoding: UTF-8 -# This file is auto-generated from the current state of the database. Instead -# of editing this file, please use the migrations feature of Active Record to -# incrementally modify your database, and then regenerate this schema definition. -# -# Note that this schema.rb definition is the authoritative source for your -# database schema. If you need to create the application database on another -# system, you should be using db:schema:load, not running all the migrations -# from scratch. The latter is a flawed and unsustainable approach (the more migrations -# you'll amass, the slower it'll run and the greater likelihood for issues). -# -# It's strongly recommended that you check this file into your version control system. - -ActiveRecord::Schema.define(version: 20190523225323) do - - # These are extensions that must be enabled in order to support this database - enable_extension "plpgsql" - enable_extension "hstore" - enable_extension "pg_trgm" - enable_extension "unaccent" - - create_table "accounts", force: :cascade do |t| - t.integer "accountable_id" - t.string "accountable_type" - t.integer "balance", default: 0 - t.integer "max_allowed_balance" - t.integer "min_allowed_balance" - t.boolean "flagged" - t.datetime "created_at" - t.datetime "updated_at" - t.integer "organization_id" - end - - add_index "accounts", ["accountable_type", "accountable_id"], name: "index_accounts_on_accountable_type_and_accountable_id", using: :btree - add_index "accounts", ["organization_id"], name: "index_accounts_on_organization_id", using: :btree - - create_table "active_admin_comments", force: :cascade do |t| - t.string "namespace" - t.text "body" - t.string "resource_id", null: false - t.string "resource_type", null: false - t.integer "author_id" - t.string "author_type" - t.datetime "created_at" - t.datetime "updated_at" - end - - add_index "active_admin_comments", ["author_type", "author_id"], name: "index_active_admin_comments_on_author_type_and_author_id", using: :btree - add_index "active_admin_comments", ["namespace"], name: "index_active_admin_comments_on_namespace", using: :btree - add_index "active_admin_comments", ["resource_type", "resource_id"], name: "index_active_admin_comments_on_resource_type_and_resource_id", using: :btree - - create_table "categories", force: :cascade do |t| - t.datetime "created_at" - t.datetime "updated_at" - t.hstore "name_translations" - end - - create_table "device_tokens", force: :cascade do |t| - t.integer "user_id", null: false - t.string "token", null: false - t.datetime "created_at" - t.datetime "updated_at" - end - - add_index "device_tokens", ["user_id", "token"], name: "index_device_tokens_on_user_id_and_token", unique: true, using: :btree - - create_table "documents", force: :cascade do |t| - t.integer "documentable_id" - t.string "documentable_type" - t.text "title" - t.text "content" - t.string "label" - t.datetime "created_at" - t.datetime "updated_at" - end - - add_index "documents", ["documentable_id", "documentable_type"], name: "index_documents_on_documentable_id_and_documentable_type", using: :btree - add_index "documents", ["label"], name: "index_documents_on_label", using: :btree - - create_table "events", force: :cascade do |t| - t.integer "action", null: false - t.integer "post_id" - t.integer "member_id" - t.integer "transfer_id" - t.datetime "created_at" - t.datetime "updated_at" - end - - add_index "events", ["member_id"], name: "index_events_on_member_id", where: "(member_id IS NOT NULL)", using: :btree - add_index "events", ["post_id"], name: "index_events_on_post_id", where: "(post_id IS NOT NULL)", using: :btree - add_index "events", ["transfer_id"], name: "index_events_on_transfer_id", where: "(transfer_id IS NOT NULL)", using: :btree - - create_table "members", force: :cascade do |t| - t.integer "user_id" - t.integer "organization_id" - t.boolean "manager" - t.datetime "created_at" - t.datetime "updated_at" - t.date "entry_date" - t.integer "member_uid" - t.boolean "active", default: true - end - - add_index "members", ["organization_id"], name: "index_members_on_organization_id", using: :btree - add_index "members", ["user_id"], name: "index_members_on_user_id", using: :btree - - create_table "movements", force: :cascade do |t| - t.integer "account_id" - t.integer "transfer_id" - t.integer "amount" - t.datetime "created_at" - t.datetime "updated_at" - end - - add_index "movements", ["account_id"], name: "index_movements_on_account_id", using: :btree - add_index "movements", ["transfer_id"], name: "index_movements_on_transfer_id", using: :btree - - create_table "organizations", force: :cascade do |t| - t.string "name", limit: 255, null: false - t.datetime "created_at" - t.datetime "updated_at" - t.integer "reg_number_seq" - t.string "theme" - t.string "email" - t.string "phone" - t.string "web" - t.text "public_opening_times" - t.text "description" - t.text "address" - t.string "neighborhood" - t.string "city" - t.string "domain" - end - - add_index "organizations", ["name"], name: "index_organizations_on_name", unique: true, using: :btree - - create_table "posts", force: :cascade do |t| - t.string "title" - t.string "type" - t.integer "category_id" - t.integer "user_id" - t.text "description" - t.date "start_on" - t.date "end_on" - t.datetime "created_at" - t.datetime "updated_at" - t.text "tags", array: true - t.integer "organization_id" - t.boolean "active", default: true - t.boolean "is_group", default: false - t.tsvector "tsv" - end - - add_index "posts", ["category_id"], name: "index_posts_on_category_id", using: :btree - add_index "posts", ["organization_id"], name: "index_posts_on_organization_id", using: :btree - add_index "posts", ["tags"], name: "index_posts_on_tags", using: :gin - add_index "posts", ["tsv"], name: "index_posts_on_tsv", using: :gin - add_index "posts", ["user_id"], name: "index_posts_on_user_id", using: :btree - - create_table "push_notifications", force: :cascade do |t| - t.integer "event_id", null: false - t.integer "device_token_id", null: false - t.datetime "processed_at" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.string "title", default: "", null: false - t.string "body", default: "", null: false - t.json "data", default: {}, null: false - end - - create_table "transfers", force: :cascade do |t| - t.integer "post_id" - t.text "reason" - t.integer "operator_id" - t.datetime "created_at" - t.datetime "updated_at" - end - - add_index "transfers", ["operator_id"], name: "index_transfers_on_operator_id", using: :btree - add_index "transfers", ["post_id"], name: "index_transfers_on_post_id", using: :btree - - create_table "users", force: :cascade do |t| - t.string "username", null: false - t.string "email", null: false - t.date "date_of_birth" - t.string "identity_document" - t.string "phone" - t.string "alt_phone" - t.text "address" - t.datetime "created_at" - t.datetime "updated_at" - t.datetime "deleted_at" - t.string "gender" - t.text "description" - t.boolean "active", default: true - t.datetime "terms_accepted_at" - t.string "encrypted_password", default: "", null: false - t.string "reset_password_token" - t.datetime "reset_password_sent_at" - t.datetime "remember_created_at" - t.integer "sign_in_count", default: 0 - t.datetime "current_sign_in_at" - t.datetime "last_sign_in_at" - t.string "current_sign_in_ip" - t.string "last_sign_in_ip" - t.string "confirmation_token" - t.datetime "confirmed_at" - t.datetime "confirmation_sent_at" - t.string "unconfirmed_email" - t.integer "failed_attempts", default: 0 - t.string "unlock_token" - t.datetime "locked_at" - t.string "locale", default: "es" - t.boolean "notifications", default: true - t.boolean "push_notifications", default: true, null: false - end - - add_index "users", ["email"], name: "index_users_on_email", using: :btree - - add_foreign_key "accounts", "organizations" - add_foreign_key "events", "members", name: "events_member_id_fkey" - add_foreign_key "events", "posts", name: "events_post_id_fkey" - add_foreign_key "events", "transfers", name: "events_transfer_id_fkey" - add_foreign_key "push_notifications", "device_tokens" - add_foreign_key "push_notifications", "events" -end diff --git a/db/structure.sql b/db/structure.sql new file mode 100644 index 000000000..5a2b8d516 --- /dev/null +++ b/db/structure.sql @@ -0,0 +1,1141 @@ +-- +-- PostgreSQL database dump +-- + +-- Dumped from database version 9.5.14 +-- Dumped by pg_dump version 9.5.14 + +SET statement_timeout = 0; +SET lock_timeout = 0; +SET client_encoding = 'UTF8'; +SET standard_conforming_strings = on; +SELECT pg_catalog.set_config('search_path', '', false); +SET check_function_bodies = false; +SET client_min_messages = warning; +SET row_security = off; + +-- +-- Name: plpgsql; Type: EXTENSION; Schema: -; Owner: - +-- + +CREATE EXTENSION IF NOT EXISTS plpgsql WITH SCHEMA pg_catalog; + + +-- +-- Name: EXTENSION plpgsql; Type: COMMENT; Schema: -; Owner: - +-- + +COMMENT ON EXTENSION plpgsql IS 'PL/pgSQL procedural language'; + + +-- +-- Name: hstore; Type: EXTENSION; Schema: -; Owner: - +-- + +CREATE EXTENSION IF NOT EXISTS hstore WITH SCHEMA public; + + +-- +-- Name: EXTENSION hstore; Type: COMMENT; Schema: -; Owner: - +-- + +COMMENT ON EXTENSION hstore IS 'data type for storing sets of (key, value) pairs'; + + +-- +-- Name: pg_trgm; Type: EXTENSION; Schema: -; Owner: - +-- + +CREATE EXTENSION IF NOT EXISTS pg_trgm WITH SCHEMA public; + + +-- +-- Name: EXTENSION pg_trgm; Type: COMMENT; Schema: -; Owner: - +-- + +COMMENT ON EXTENSION pg_trgm IS 'text similarity measurement and index searching based on trigrams'; + + +-- +-- Name: unaccent; Type: EXTENSION; Schema: -; Owner: - +-- + +CREATE EXTENSION IF NOT EXISTS unaccent WITH SCHEMA public; + + +-- +-- Name: EXTENSION unaccent; Type: COMMENT; Schema: -; Owner: - +-- + +COMMENT ON EXTENSION unaccent IS 'text search dictionary that removes accents'; + + +-- +-- Name: posts_trigger(); Type: FUNCTION; Schema: public; Owner: - +-- + +CREATE FUNCTION public.posts_trigger() RETURNS trigger + LANGUAGE plpgsql + AS $$ + begin + new.tsv := + to_tsvector('simple', unaccent(coalesce(new.title::text, ''))) || + to_tsvector('simple', unaccent(coalesce(new.description::text, ''))) || + to_tsvector('simple', unaccent(coalesce(new.tags::text, ''))); + return new; + end + $$; + + +SET default_tablespace = ''; + +SET default_with_oids = false; + +-- +-- Name: accounts; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.accounts ( + id integer NOT NULL, + accountable_id integer, + accountable_type character varying, + balance integer DEFAULT 0, + max_allowed_balance integer, + min_allowed_balance integer, + flagged boolean, + created_at timestamp without time zone, + updated_at timestamp without time zone, + organization_id integer +); + + +-- +-- Name: accounts_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.accounts_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: accounts_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.accounts_id_seq OWNED BY public.accounts.id; + + +-- +-- Name: active_admin_comments; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.active_admin_comments ( + id integer NOT NULL, + namespace character varying, + body text, + resource_id character varying NOT NULL, + resource_type character varying NOT NULL, + author_id integer, + author_type character varying, + created_at timestamp without time zone, + updated_at timestamp without time zone +); + + +-- +-- Name: active_admin_comments_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.active_admin_comments_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: active_admin_comments_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.active_admin_comments_id_seq OWNED BY public.active_admin_comments.id; + + +-- +-- Name: categories; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.categories ( + id integer NOT NULL, + created_at timestamp without time zone, + updated_at timestamp without time zone, + name_translations public.hstore +); + + +-- +-- Name: categories_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.categories_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: categories_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.categories_id_seq OWNED BY public.categories.id; + + +-- +-- Name: device_tokens; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.device_tokens ( + id integer NOT NULL, + user_id integer NOT NULL, + token character varying NOT NULL, + created_at timestamp without time zone, + updated_at timestamp without time zone +); + + +-- +-- Name: device_tokens_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.device_tokens_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: device_tokens_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.device_tokens_id_seq OWNED BY public.device_tokens.id; + + +-- +-- Name: documents; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.documents ( + id integer NOT NULL, + documentable_id integer, + documentable_type character varying, + title text, + content text, + label character varying, + created_at timestamp without time zone, + updated_at timestamp without time zone +); + + +-- +-- Name: documents_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.documents_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: documents_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.documents_id_seq OWNED BY public.documents.id; + + +-- +-- Name: events; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.events ( + id integer NOT NULL, + action integer NOT NULL, + post_id integer, + member_id integer, + transfer_id integer, + created_at timestamp without time zone, + updated_at timestamp without time zone +); + + +-- +-- Name: events_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.events_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: events_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.events_id_seq OWNED BY public.events.id; + + +-- +-- Name: members; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.members ( + id integer NOT NULL, + user_id integer, + organization_id integer, + manager boolean, + created_at timestamp without time zone, + updated_at timestamp without time zone, + entry_date date, + member_uid integer, + active boolean DEFAULT true +); + + +-- +-- Name: members_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.members_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: members_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.members_id_seq OWNED BY public.members.id; + + +-- +-- Name: movements; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.movements ( + id integer NOT NULL, + account_id integer, + transfer_id integer, + amount integer, + created_at timestamp without time zone, + updated_at timestamp without time zone +); + + +-- +-- Name: movements_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.movements_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: movements_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.movements_id_seq OWNED BY public.movements.id; + + +-- +-- Name: organizations; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.organizations ( + id integer NOT NULL, + name character varying(255) NOT NULL, + created_at timestamp without time zone, + updated_at timestamp without time zone, + reg_number_seq integer, + theme character varying, + email character varying, + phone character varying, + web character varying, + public_opening_times text, + description text, + address text, + neighborhood character varying, + city character varying, + domain character varying +); + + +-- +-- Name: organizations_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.organizations_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: organizations_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.organizations_id_seq OWNED BY public.organizations.id; + + +-- +-- Name: posts; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.posts ( + id integer NOT NULL, + title character varying, + type character varying, + category_id integer, + user_id integer, + description text, + start_on date, + end_on date, + created_at timestamp without time zone, + updated_at timestamp without time zone, + tags text[], + organization_id integer, + active boolean DEFAULT true, + is_group boolean DEFAULT false, + tsv tsvector +); + + +-- +-- Name: posts_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.posts_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: posts_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.posts_id_seq OWNED BY public.posts.id; + + +-- +-- Name: push_notifications; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.push_notifications ( + id integer NOT NULL, + event_id integer NOT NULL, + device_token_id integer NOT NULL, + processed_at timestamp without time zone, + created_at timestamp without time zone NOT NULL, + updated_at timestamp without time zone NOT NULL, + title character varying DEFAULT ''::character varying NOT NULL, + body character varying DEFAULT ''::character varying NOT NULL, + data json DEFAULT '{}'::json NOT NULL +); + + +-- +-- Name: push_notifications_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.push_notifications_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: push_notifications_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.push_notifications_id_seq OWNED BY public.push_notifications.id; + + +-- +-- Name: schema_migrations; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.schema_migrations ( + version character varying NOT NULL +); + + +-- +-- Name: transfers; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.transfers ( + id integer NOT NULL, + post_id integer, + reason text, + operator_id integer, + created_at timestamp without time zone, + updated_at timestamp without time zone +); + + +-- +-- Name: transfers_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.transfers_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: transfers_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.transfers_id_seq OWNED BY public.transfers.id; + + +-- +-- Name: users; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.users ( + id integer NOT NULL, + username character varying NOT NULL, + email character varying NOT NULL, + date_of_birth date, + identity_document character varying, + phone character varying, + alt_phone character varying, + address text, + created_at timestamp without time zone, + updated_at timestamp without time zone, + deleted_at timestamp without time zone, + gender character varying, + description text, + active boolean DEFAULT true, + terms_accepted_at timestamp without time zone, + encrypted_password character varying DEFAULT ''::character varying NOT NULL, + reset_password_token character varying, + reset_password_sent_at timestamp without time zone, + remember_created_at timestamp without time zone, + sign_in_count integer DEFAULT 0, + current_sign_in_at timestamp without time zone, + last_sign_in_at timestamp without time zone, + current_sign_in_ip character varying, + last_sign_in_ip character varying, + confirmation_token character varying, + confirmed_at timestamp without time zone, + confirmation_sent_at timestamp without time zone, + unconfirmed_email character varying, + failed_attempts integer DEFAULT 0, + unlock_token character varying, + locked_at timestamp without time zone, + locale character varying DEFAULT 'es'::character varying, + notifications boolean DEFAULT true, + push_notifications boolean DEFAULT true NOT NULL +); + + +-- +-- Name: users_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.users_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: users_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.users_id_seq OWNED BY public.users.id; + + +-- +-- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.accounts ALTER COLUMN id SET DEFAULT nextval('public.accounts_id_seq'::regclass); + + +-- +-- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.active_admin_comments ALTER COLUMN id SET DEFAULT nextval('public.active_admin_comments_id_seq'::regclass); + + +-- +-- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.categories ALTER COLUMN id SET DEFAULT nextval('public.categories_id_seq'::regclass); + + +-- +-- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.device_tokens ALTER COLUMN id SET DEFAULT nextval('public.device_tokens_id_seq'::regclass); + + +-- +-- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.documents ALTER COLUMN id SET DEFAULT nextval('public.documents_id_seq'::regclass); + + +-- +-- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.events ALTER COLUMN id SET DEFAULT nextval('public.events_id_seq'::regclass); + + +-- +-- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.members ALTER COLUMN id SET DEFAULT nextval('public.members_id_seq'::regclass); + + +-- +-- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.movements ALTER COLUMN id SET DEFAULT nextval('public.movements_id_seq'::regclass); + + +-- +-- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.organizations ALTER COLUMN id SET DEFAULT nextval('public.organizations_id_seq'::regclass); + + +-- +-- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.posts ALTER COLUMN id SET DEFAULT nextval('public.posts_id_seq'::regclass); + + +-- +-- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.push_notifications ALTER COLUMN id SET DEFAULT nextval('public.push_notifications_id_seq'::regclass); + + +-- +-- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.transfers ALTER COLUMN id SET DEFAULT nextval('public.transfers_id_seq'::regclass); + + +-- +-- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.users ALTER COLUMN id SET DEFAULT nextval('public.users_id_seq'::regclass); + + +-- +-- Name: accounts_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.accounts + ADD CONSTRAINT accounts_pkey PRIMARY KEY (id); + + +-- +-- Name: active_admin_comments_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.active_admin_comments + ADD CONSTRAINT active_admin_comments_pkey PRIMARY KEY (id); + + +-- +-- Name: categories_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.categories + ADD CONSTRAINT categories_pkey PRIMARY KEY (id); + + +-- +-- Name: device_tokens_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.device_tokens + ADD CONSTRAINT device_tokens_pkey PRIMARY KEY (id); + + +-- +-- Name: documents_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.documents + ADD CONSTRAINT documents_pkey PRIMARY KEY (id); + + +-- +-- Name: events_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.events + ADD CONSTRAINT events_pkey PRIMARY KEY (id); + + +-- +-- Name: members_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.members + ADD CONSTRAINT members_pkey PRIMARY KEY (id); + + +-- +-- Name: movements_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.movements + ADD CONSTRAINT movements_pkey PRIMARY KEY (id); + + +-- +-- Name: organizations_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.organizations + ADD CONSTRAINT organizations_pkey PRIMARY KEY (id); + + +-- +-- Name: posts_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.posts + ADD CONSTRAINT posts_pkey PRIMARY KEY (id); + + +-- +-- Name: push_notifications_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.push_notifications + ADD CONSTRAINT push_notifications_pkey PRIMARY KEY (id); + + +-- +-- Name: transfers_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.transfers + ADD CONSTRAINT transfers_pkey PRIMARY KEY (id); + + +-- +-- Name: users_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.users + ADD CONSTRAINT users_pkey PRIMARY KEY (id); + + +-- +-- Name: index_accounts_on_accountable_type_and_accountable_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX index_accounts_on_accountable_type_and_accountable_id ON public.accounts USING btree (accountable_type, accountable_id); + + +-- +-- Name: index_accounts_on_organization_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX index_accounts_on_organization_id ON public.accounts USING btree (organization_id); + + +-- +-- Name: index_active_admin_comments_on_author_type_and_author_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX index_active_admin_comments_on_author_type_and_author_id ON public.active_admin_comments USING btree (author_type, author_id); + + +-- +-- Name: index_active_admin_comments_on_namespace; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX index_active_admin_comments_on_namespace ON public.active_admin_comments USING btree (namespace); + + +-- +-- Name: index_active_admin_comments_on_resource_type_and_resource_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX index_active_admin_comments_on_resource_type_and_resource_id ON public.active_admin_comments USING btree (resource_type, resource_id); + + +-- +-- Name: index_device_tokens_on_user_id_and_token; Type: INDEX; Schema: public; Owner: - +-- + +CREATE UNIQUE INDEX index_device_tokens_on_user_id_and_token ON public.device_tokens USING btree (user_id, token); + + +-- +-- Name: index_documents_on_documentable_id_and_documentable_type; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX index_documents_on_documentable_id_and_documentable_type ON public.documents USING btree (documentable_id, documentable_type); + + +-- +-- Name: index_documents_on_label; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX index_documents_on_label ON public.documents USING btree (label); + + +-- +-- Name: index_events_on_member_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX index_events_on_member_id ON public.events USING btree (member_id) WHERE (member_id IS NOT NULL); + + +-- +-- Name: index_events_on_post_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX index_events_on_post_id ON public.events USING btree (post_id) WHERE (post_id IS NOT NULL); + + +-- +-- Name: index_events_on_transfer_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX index_events_on_transfer_id ON public.events USING btree (transfer_id) WHERE (transfer_id IS NOT NULL); + + +-- +-- Name: index_members_on_organization_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX index_members_on_organization_id ON public.members USING btree (organization_id); + + +-- +-- Name: index_members_on_user_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX index_members_on_user_id ON public.members USING btree (user_id); + + +-- +-- Name: index_movements_on_account_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX index_movements_on_account_id ON public.movements USING btree (account_id); + + +-- +-- Name: index_movements_on_transfer_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX index_movements_on_transfer_id ON public.movements USING btree (transfer_id); + + +-- +-- Name: index_organizations_on_name; Type: INDEX; Schema: public; Owner: - +-- + +CREATE UNIQUE INDEX index_organizations_on_name ON public.organizations USING btree (name); + + +-- +-- Name: index_posts_on_category_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX index_posts_on_category_id ON public.posts USING btree (category_id); + + +-- +-- Name: index_posts_on_organization_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX index_posts_on_organization_id ON public.posts USING btree (organization_id); + + +-- +-- Name: index_posts_on_tags; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX index_posts_on_tags ON public.posts USING gin (tags); + + +-- +-- Name: index_posts_on_tsv; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX index_posts_on_tsv ON public.posts USING gin (tsv); + + +-- +-- Name: index_posts_on_user_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX index_posts_on_user_id ON public.posts USING btree (user_id); + + +-- +-- Name: index_transfers_on_operator_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX index_transfers_on_operator_id ON public.transfers USING btree (operator_id); + + +-- +-- Name: index_transfers_on_post_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX index_transfers_on_post_id ON public.transfers USING btree (post_id); + + +-- +-- Name: index_users_on_email; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX index_users_on_email ON public.users USING btree (email); + + +-- +-- Name: unique_schema_migrations; Type: INDEX; Schema: public; Owner: - +-- + +CREATE UNIQUE INDEX unique_schema_migrations ON public.schema_migrations USING btree (version); + + +-- +-- Name: tsvectorupdate; Type: TRIGGER; Schema: public; Owner: - +-- + +CREATE TRIGGER tsvectorupdate BEFORE INSERT OR UPDATE ON public.posts FOR EACH ROW EXECUTE PROCEDURE public.posts_trigger(); + + +-- +-- Name: events_member_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.events + ADD CONSTRAINT events_member_id_fkey FOREIGN KEY (member_id) REFERENCES public.members(id); + + +-- +-- Name: events_post_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.events + ADD CONSTRAINT events_post_id_fkey FOREIGN KEY (post_id) REFERENCES public.posts(id); + + +-- +-- Name: events_transfer_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.events + ADD CONSTRAINT events_transfer_id_fkey FOREIGN KEY (transfer_id) REFERENCES public.transfers(id); + + +-- +-- Name: fk_rails_1ceb778440; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.accounts + ADD CONSTRAINT fk_rails_1ceb778440 FOREIGN KEY (organization_id) REFERENCES public.organizations(id); + + +-- +-- Name: fk_rails_36fb6ef1a8; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.push_notifications + ADD CONSTRAINT fk_rails_36fb6ef1a8 FOREIGN KEY (device_token_id) REFERENCES public.device_tokens(id); + + +-- +-- Name: fk_rails_79a395b2d7; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.push_notifications + ADD CONSTRAINT fk_rails_79a395b2d7 FOREIGN KEY (event_id) REFERENCES public.events(id); + + +-- +-- PostgreSQL database dump complete +-- + +SET search_path TO "$user", public; + +INSERT INTO schema_migrations (version) VALUES ('1'); + +INSERT INTO schema_migrations (version) VALUES ('2'); + +INSERT INTO schema_migrations (version) VALUES ('20121019101022'); + +INSERT INTO schema_migrations (version) VALUES ('20121104004639'); + +INSERT INTO schema_migrations (version) VALUES ('20121104085711'); + +INSERT INTO schema_migrations (version) VALUES ('20121121233818'); + +INSERT INTO schema_migrations (version) VALUES ('20130214175758'); + +INSERT INTO schema_migrations (version) VALUES ('20130214181128'); + +INSERT INTO schema_migrations (version) VALUES ('20130222185624'); + +INSERT INTO schema_migrations (version) VALUES ('20130425165150'); + +INSERT INTO schema_migrations (version) VALUES ('20130508085004'); + +INSERT INTO schema_migrations (version) VALUES ('20130513092219'); + +INSERT INTO schema_migrations (version) VALUES ('20130514094755'); + +INSERT INTO schema_migrations (version) VALUES ('20130618210236'); + +INSERT INTO schema_migrations (version) VALUES ('20130621102219'); + +INSERT INTO schema_migrations (version) VALUES ('20130621103053'); + +INSERT INTO schema_migrations (version) VALUES ('20130621103501'); + +INSERT INTO schema_migrations (version) VALUES ('20130621105452'); + +INSERT INTO schema_migrations (version) VALUES ('20130703233851'); + +INSERT INTO schema_migrations (version) VALUES ('20130703234011'); + +INSERT INTO schema_migrations (version) VALUES ('20130703234042'); + +INSERT INTO schema_migrations (version) VALUES ('20130723160206'); + +INSERT INTO schema_migrations (version) VALUES ('20131017144321'); + +INSERT INTO schema_migrations (version) VALUES ('20131025202608'); + +INSERT INTO schema_migrations (version) VALUES ('20131027215517'); + +INSERT INTO schema_migrations (version) VALUES ('20131029202724'); + +INSERT INTO schema_migrations (version) VALUES ('20131103221044'); + +INSERT INTO schema_migrations (version) VALUES ('20131104004235'); + +INSERT INTO schema_migrations (version) VALUES ('20131104013634'); + +INSERT INTO schema_migrations (version) VALUES ('20131104013829'); + +INSERT INTO schema_migrations (version) VALUES ('20131104032622'); + +INSERT INTO schema_migrations (version) VALUES ('20131220160257'); + +INSERT INTO schema_migrations (version) VALUES ('20131227110122'); + +INSERT INTO schema_migrations (version) VALUES ('20131227142805'); + +INSERT INTO schema_migrations (version) VALUES ('20131227155440'); + +INSERT INTO schema_migrations (version) VALUES ('20131231110424'); + +INSERT INTO schema_migrations (version) VALUES ('20140119161433'); + +INSERT INTO schema_migrations (version) VALUES ('20140513141718'); + +INSERT INTO schema_migrations (version) VALUES ('20140514225527'); + +INSERT INTO schema_migrations (version) VALUES ('20150329193421'); + +INSERT INTO schema_migrations (version) VALUES ('20150330200315'); + +INSERT INTO schema_migrations (version) VALUES ('20150422162806'); + +INSERT INTO schema_migrations (version) VALUES ('20180221161343'); + +INSERT INTO schema_migrations (version) VALUES ('20180501093846'); + +INSERT INTO schema_migrations (version) VALUES ('20180514193153'); + +INSERT INTO schema_migrations (version) VALUES ('20180524143938'); + +INSERT INTO schema_migrations (version) VALUES ('20180525141138'); + +INSERT INTO schema_migrations (version) VALUES ('20180529144243'); + +INSERT INTO schema_migrations (version) VALUES ('20180530180546'); + +INSERT INTO schema_migrations (version) VALUES ('20180604145622'); + +INSERT INTO schema_migrations (version) VALUES ('20180828160700'); + +INSERT INTO schema_migrations (version) VALUES ('20180831161349'); + +INSERT INTO schema_migrations (version) VALUES ('20180924164456'); + +INSERT INTO schema_migrations (version) VALUES ('20181004200104'); + +INSERT INTO schema_migrations (version) VALUES ('20190319121401'); + +INSERT INTO schema_migrations (version) VALUES ('20190322180602'); + +INSERT INTO schema_migrations (version) VALUES ('20190411192828'); + +INSERT INTO schema_migrations (version) VALUES ('20190412163011'); + +INSERT INTO schema_migrations (version) VALUES ('20190523213421'); + +INSERT INTO schema_migrations (version) VALUES ('20190523225323'); + From 5d0ec9ee9e03c6b732cbc3d6a58d20d7653ba31b Mon Sep 17 00:00:00 2001 From: Enrico Stano Date: Fri, 24 May 2019 19:01:49 +0200 Subject: [PATCH 8/8] Specs++ --- spec/controllers/offers_controller_spec.rb | 89 +++++++++++++++++++--- 1 file changed, 80 insertions(+), 9 deletions(-) diff --git a/spec/controllers/offers_controller_spec.rb b/spec/controllers/offers_controller_spec.rb index cca4c262c..9eccf526d 100644 --- a/spec/controllers/offers_controller_spec.rb +++ b/spec/controllers/offers_controller_spec.rb @@ -12,6 +12,12 @@ organization: organization, category: test_category) end + let!(:other_offer) do + Fabricate(:offer, + user: another_member.user, + organization: organization, + category: test_category) + end include_context "stub browser locale" @@ -22,14 +28,47 @@ it "populates an array of offers" do login(another_member.user) - get "index" - expect(assigns(:offers)).to eq([offer]) + get :index + + expect(assigns(:offers)).to eq([other_offer, offer]) + end + + context "when one offer is not active" do + before do + other_offer.active = false + other_offer.save! + end + + it "only returns active offers" do + login(another_member.user) + + get :index + + expect(assigns(:offers)).to eq([offer]) + end + end + + context "when one offer's user is not active" do + before do + member.active = false + member.save! + end + + it "only returns offers from active users" do + login(another_member.user) + + get :index + + expect(assigns(:offers)).to eq([other_offer]) + end end end context "with another organization" do it "skips the original org's offers" do login(yet_another_member.user) - get "index" + + get :index + expect(assigns(:offers)).to eq([]) end end @@ -37,19 +76,51 @@ describe "GET #index (search)" do before { login(another_member.user) } + before do + offer.title = "Queridos compañeros" + offer.save! + end it "populates an array of offers" do - get "index", q: offer.title.split(/\s/).first + get :index, q: 'compañeros' - expect(assigns(:offers).size).to eq 1 - expect(assigns(:offers)[0]).to eq offer - expect(assigns(:offers).to_a).to eq([offer]) + expect(assigns(:offers)).to eq([offer]) end it "allows to search by partial word" do - get :index, q: offer.title.split(/\s/).first[0..-2] + get :index, q: 'compañ' + + expect(assigns(:offers)).to eq([offer]) + end + + context "when one offer is not active" do + before do + other_offer.active = false + other_offer.save! + end + + it "only returns active offers" do + login(another_member.user) + + get :index - expect(assigns(:offers)).to include offer + expect(assigns(:offers)).to eq([offer]) + end + end + + context "when one offer's user is not active" do + before do + member.active = false + member.save! + end + + it "only returns offers from active users" do + login(another_member.user) + + get :index + + expect(assigns(:offers)).to eq([other_offer]) + end end end