Instantly share code, notes, and snippets.
Created
October 3, 2014 07:57
-
Star
0
(0)
You must be signed in to star a gist -
Fork
0
(0)
You must be signed in to fork a gist
-
-
Save dgertych-monterail/981ca8ccf2269bba6548 to your computer and use it in GitHub Desktop.
Tags cache issue solved with https://github.com/jenseng/hair_trigger
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| diff --git a/README.md b/README.md | |
| index e4e7348..3aa3845 100644 | |
| --- a/README.md | |
| +++ b/README.md | |
| @@ -29,6 +29,10 @@ Okta trial information you can find [here](https://monterail.hackpad.com/Cooleaf | |
| If there are two ENV variables set: `BASIC_USERNAME` and `BASIC_PASSWORD` | |
| whole application will be guarded by basic auth. | |
| +### Tags Cache | |
| +Tags cache attribute for Role and Persona is updated by database stored procedure on taggings table. | |
| +Checkout details in `app/models/taggins.rb` | |
| + | |
| ### Testing | |
| We are using [poltergeist](https://github.com/jonleighton/poltergeist/tree/v1.5.0) - see [installation instructions](https://github.com/jonleighton/poltergeist/tree/v1.5.0#installation) | |
| diff --git a/app/controllers/api/v1/hr/structures.rb b/app/controllers/api/v1/hr/structures.rb | |
| index f46c98f..00f3bd4 100644 | |
| --- a/app/controllers/api/v1/hr/structures.rb | |
| +++ b/app/controllers/api/v1/hr/structures.rb | |
| @@ -59,7 +59,7 @@ module API::V1::HR | |
| Tag.transaction do | |
| role = roles[user[:id].to_i] | |
| tag = tags[user[:tag].to_i] | |
| - add_tag_to_role(role, tag) | |
| + role.tags << tag | |
| end | |
| end | |
| end | |
| @@ -98,11 +98,6 @@ module API::V1::HR | |
| end | |
| end | |
| - def add_tag_to_role(role, tag) | |
| - role.tags << tag | |
| - role.refresh_tags_cache | |
| - end | |
| - | |
| def map_users_hash_with(key) | |
| permitted_params[:users].try(:map) { |user| user[key].to_i } | |
| end | |
| diff --git a/app/controllers/api/v1/hr/users.rb b/app/controllers/api/v1/hr/users.rb | |
| index 7af32f2..7489e2d 100644 | |
| --- a/app/controllers/api/v1/hr/users.rb | |
| +++ b/app/controllers/api/v1/hr/users.rb | |
| @@ -115,7 +115,6 @@ module API::V1::HR | |
| Tag.transaction do | |
| update_structure_tags(role, permitted_params[:structures]) | |
| update_hidden_tags(role, permitted_params[:hidden].uniq) | |
| - role.refresh_tags_cache | |
| end | |
| represent role.user, current_organization, with: ::HR::UserRepresenter | |
| diff --git a/app/controllers/api/v1/main/users.rb b/app/controllers/api/v1/main/users.rb | |
| index b3d29ae..7bf6179 100644 | |
| --- a/app/controllers/api/v1/main/users.rb | |
| +++ b/app/controllers/api/v1/main/users.rb | |
| @@ -98,7 +98,6 @@ module API::V1::Main | |
| if role_params = user_params.delete(:role) | |
| Tag.transaction do | |
| update_structure_tags(role, role_params[:structures]) | |
| - role.refresh_tags_cache | |
| end | |
| end | |
| @@ -109,7 +108,6 @@ module API::V1::Main | |
| role.tags.delete(role.tags.interest) | |
| role.tags << current_organization.tags.interest.where(id: interests.uniq). | |
| where(active: true) | |
| - role.refresh_tags_cache | |
| end | |
| end | |
| diff --git a/app/models/persona.rb b/app/models/persona.rb | |
| index 9b14528..5833bd8 100644 | |
| --- a/app/models/persona.rb | |
| +++ b/app/models/persona.rb | |
| @@ -2,10 +2,4 @@ class Persona < ActiveRecord::Base | |
| belongs_to :personable, polymorphic: true | |
| has_many :taggings, as: :taggable, dependent: :destroy | |
| has_many :tags, through: :taggings | |
| - | |
| - after_create :refresh_tags_cache | |
| - | |
| - def refresh_tags_cache | |
| - self.update_attributes!(tags_cache: tag_ids) | |
| - end | |
| end | |
| diff --git a/app/models/role.rb b/app/models/role.rb | |
| index b5ed1eb..51c770f 100644 | |
| --- a/app/models/role.rb | |
| +++ b/app/models/role.rb | |
| @@ -17,10 +17,6 @@ class Role < ActiveRecord::Base | |
| scope :active, ->{ where(active: true) } | |
| - def refresh_tags_cache | |
| - self.update_attributes!(tags_cache: tag_ids) | |
| - end | |
| - | |
| def self.for(organization) | |
| find_by(organization: organization) | |
| end | |
| diff --git a/app/models/tagging.rb b/app/models/tagging.rb | |
| index 5c66273..e4a8a8f 100644 | |
| --- a/app/models/tagging.rb | |
| +++ b/app/models/tagging.rb | |
| @@ -8,4 +8,25 @@ class Tagging < ActiveRecord::Base | |
| def interest? | |
| tag.try(:type) == "interest" | |
| end | |
| + | |
| + trigger.after(:insert, :delete). | |
| + declare('row RECORD; tbl_name TEXT; tags_cache_sql TEXT;') do | |
| + <<-SQL | |
| + IF TG_OP = 'INSERT' THEN | |
| + row := NEW; | |
| + ELSIF TG_OP = 'DELETE' THEN | |
| + row := OLD; | |
| + END IF; | |
| + IF row.taggable_type IN ('Persona', 'Role') THEN | |
| + tbl_name := LOWER(row.taggable_type) || 's'; | |
| + tags_cache_sql = 'SELECT tag_id FROM taggings' | |
| + || ' WHERE taggable_type = ' || quote_literal(row.taggable_type) | |
| + || ' AND taggable_id = ' || quote_literal(row.taggable_id); | |
| + | |
| + EXECUTE 'UPDATE ' || quote_ident(tbl_name) | |
| + || ' SET tags_cache = ARRAY(' || tags_cache_sql || ')' | |
| + || ' WHERE id = ' || quote_literal(row.taggable_id); | |
| + END IF; | |
| + SQL | |
| + end | |
| end | |
| diff --git a/app/services/registration_form.rb b/app/services/registration_form.rb | |
| index d856bcb..2597321 100644 | |
| --- a/app/services/registration_form.rb | |
| +++ b/app/services/registration_form.rb | |
| @@ -158,7 +158,6 @@ class RegistrationForm | |
| def persist! | |
| user.save! | |
| - role.refresh_tags_cache | |
| registration.destroy | |
| end | |
| diff --git a/db/migrate/20141001110815_create_trigger_taggings_insert_delete.rb b/db/migrate/20141001110815_create_trigger_taggings_insert_delete.rb | |
| new file mode 100644 | |
| index 0000000..691997a | |
| --- /dev/null | |
| +++ b/db/migrate/20141001110815_create_trigger_taggings_insert_delete.rb | |
| @@ -0,0 +1,34 @@ | |
| +# This migration was auto-generated via `rake db:generate_trigger_migration'. | |
| +# While you can edit this file, any changes you make to the definitions here | |
| +# will be undone by the next auto-generated trigger migration. | |
| + | |
| +class CreateTriggerTaggingsInsertDelete < ActiveRecord::Migration | |
| + def up | |
| + create_trigger("taggings_after_insert_delete_row_tr", :generated => true, :compatibility => 1). | |
| + on("taggings"). | |
| + after(:insert, :delete). | |
| + declare('row RECORD; tbl_name TEXT; tags_cache_sql TEXT;') do | |
| + <<-SQL_ACTIONS | |
| + IF TG_OP = 'INSERT' THEN | |
| + row := NEW; | |
| + ELSIF TG_OP = 'DELETE' THEN | |
| + row := OLD; | |
| + END IF; | |
| + IF row.taggable_type IN ('Persona', 'Role') THEN | |
| + tbl_name := LOWER(row.taggable_type) || 's'; | |
| + tags_cache_sql = 'SELECT tag_id FROM taggings' | |
| + || ' WHERE taggable_type = ' || quote_literal(row.taggable_type) | |
| + || ' AND taggable_id = ' || quote_literal(row.taggable_id); | |
| + | |
| + EXECUTE 'UPDATE ' || quote_ident(tbl_name) | |
| + || ' SET tags_cache = ARRAY(' || tags_cache_sql || ')' | |
| + || ' WHERE id = ' || quote_literal(row.taggable_id); | |
| + END IF; | |
| + SQL_ACTIONS | |
| + end | |
| + end | |
| + | |
| + def down | |
| + drop_trigger("taggings_after_insert_delete_row_tr", "taggings", :generated => true) | |
| + end | |
| +end | |
| diff --git a/db/schema.rb b/db/schema.rb | |
| index 7a19608..8a24f4b 100644 | |
| --- a/db/schema.rb | |
| +++ b/db/schema.rb | |
| @@ -11,7 +11,7 @@ | |
| # | |
| # It's strongly recommended that you check this file into your version control system. | |
| -ActiveRecord::Schema.define(version: 20140929154205) do | |
| +ActiveRecord::Schema.define(version: 20141001110815) do | |
| # These are extensions that must be enabled in order to support this database | |
| enable_extension "plpgsql" | |
| @@ -496,4 +496,27 @@ ActiveRecord::Schema.define(version: 20140929154205) do | |
| t.datetime "updated_at" | |
| end | |
| + create_trigger("taggings_after_insert_delete_row_tr", :generated => true, :compatibility => 1). | |
| + on("taggings"). | |
| + after(:insert, :delete). | |
| + declare('row RECORD; tbl_name TEXT; tags_cache_sql TEXT;') do | |
| + <<-SQL_ACTIONS | |
| + IF TG_OP = 'INSERT' THEN | |
| + row := NEW; | |
| + ELSIF TG_OP = 'DELETE' THEN | |
| + row := OLD; | |
| + END IF; | |
| + IF row.taggable_type IN ('Persona', 'Role') THEN | |
| + tbl_name := LOWER(row.taggable_type) || 's'; | |
| + tags_cache_sql = 'SELECT tag_id FROM taggings' | |
| + || ' WHERE taggable_type = ' || quote_literal(row.taggable_type) | |
| + || ' AND taggable_id = ' || quote_literal(row.taggable_id); | |
| + | |
| + EXECUTE 'UPDATE ' || quote_ident(tbl_name) | |
| + || ' SET tags_cache = ARRAY(' || tags_cache_sql || ')' | |
| + || ' WHERE id = ' || quote_literal(row.taggable_id); | |
| + END IF; | |
| + SQL_ACTIONS | |
| + end | |
| + | |
| end | |
| diff --git a/spec/factories/personas.rb b/spec/factories/personas.rb | |
| index e703f0a..250ab95 100644 | |
| --- a/spec/factories/personas.rb | |
| +++ b/spec/factories/personas.rb | |
| @@ -11,7 +11,6 @@ FactoryGirl.define do | |
| create_list(:interest_tag, 3, | |
| organization: evaluator.personable.organization, | |
| personas: [persona]) | |
| - persona.refresh_tags_cache | |
| end | |
| end | |
| diff --git a/spec/requests/api/v1/hr/structures_spec.rb b/spec/requests/api/v1/hr/structures_spec.rb | |
| index a0277a0..aafec0b 100644 | |
| --- a/spec/requests/api/v1/hr/structures_spec.rb | |
| +++ b/spec/requests/api/v1/hr/structures_spec.rb | |
| @@ -11,11 +11,6 @@ describe API::V1::HR::Structures do | |
| "/v1/hr/structures/#{structure.id}/#{action}" | |
| end | |
| - def add_tag_to_role(role, tag) | |
| - role.tags << tag | |
| - role.refresh_tags_cache | |
| - end | |
| - | |
| before do | |
| Grape::Endpoint.before_each do |endpoint| | |
| allow(endpoint).to receive(:authenticate!).and_return(true) | |
| @@ -32,8 +27,7 @@ describe API::V1::HR::Structures do | |
| let(:role) { user_with_tag.roles.for(organization) } | |
| before do | |
| - add_tag_to_role(role, tag) | |
| - | |
| + role.tags << tag | |
| get api_path_to("users_without_tags"), organization: organization.subdomain | |
| end | |
| @@ -60,7 +54,7 @@ describe API::V1::HR::Structures do | |
| describe "with no required tags missing in the database" do | |
| let(:role) { hr.roles.for(organization) } | |
| - before { add_tag_to_role(role, tag) } | |
| + before { role.tags << tag } | |
| it "should pass" do | |
| put api_path_to("required"), basic_params |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment