{"id":13878221,"url":"https://github.com/igorkasyanchuk/sql_view","last_synced_at":"2025-04-14T06:44:06.889Z","repository":{"id":59156173,"uuid":"457514405","full_name":"igorkasyanchuk/sql_view","owner":"igorkasyanchuk","description":"Rails SQL Views made easy ;)","archived":false,"fork":false,"pushed_at":"2023-06-18T10:51:27.000Z","size":1656,"stargazers_count":51,"open_issues_count":2,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-04-07T17:22:35.525Z","etag":null,"topics":["activerecord","rails","sqlviews"],"latest_commit_sha":null,"homepage":"https://www.railsjazz.com/","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/igorkasyanchuk.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"MIT-LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2022-02-09T20:16:49.000Z","updated_at":"2024-12-20T09:24:10.000Z","dependencies_parsed_at":"2024-04-12T12:29:59.971Z","dependency_job_id":"e7d538c1-e17c-4c98-999e-0370a6ec50ae","html_url":"https://github.com/igorkasyanchuk/sql_view","commit_stats":{"total_commits":34,"total_committers":3,"mean_commits":"11.333333333333334","dds":0.05882352941176472,"last_synced_commit":"2b8d51727a3744e7057acf1670a7d38b780e618c"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/igorkasyanchuk%2Fsql_view","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/igorkasyanchuk%2Fsql_view/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/igorkasyanchuk%2Fsql_view/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/igorkasyanchuk%2Fsql_view/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/igorkasyanchuk","download_url":"https://codeload.github.com/igorkasyanchuk/sql_view/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248837264,"owners_count":21169373,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["activerecord","rails","sqlviews"],"created_at":"2024-08-06T08:01:43.143Z","updated_at":"2025-04-14T06:44:06.868Z","avatar_url":"https://github.com/igorkasyanchuk.png","language":"Ruby","readme":"# Rails + SQL View\n\n[![Listed on OpenSource-Heroes.com](https://opensource-heroes.com/badge-v1.svg)](https://opensource-heroes.com/r/igorkasyanchuk/sql_view)\n\n## The easist way to add and work with SQL view in your app.\n\nIf you are lazy and don't like to write SQL to create SQL view but you know AR use your skills to create views.\n\nProduction-ready.\n\n![Demo](docs/sql_view.gif?raw=true \"Demo\")\n\n## Usage\n\nThe most simple way to add a view is to call a generator (examples below):\n\n```bash\nrails g sql_view:view DeletedProjects 'Project.only_deleted'\nrails g sql_view:view ActiveUsers 'User.confirmed.where(active: true)' --materialized\n```\n\nDepending on whether you need a materialized view or not add `--materialized` flag (later you can change in \"view\" class). Materialized views works in Postgres.\n\nGenerator will create a file similar to:\n\n```ruby\nclass ActiveUserView \u003c SQLView::Model\n  materialized\n\n  schema -\u003e { User.where(age: 18..60) }\n\n  extend_model_with do\n    # sample how you can extend it, similar to regular AR model\n    #\n    # include SomeConcern\n    #\n    # belongs_to :user\n    # has_many :posts\n    #\n    # scope :ordered, -\u003e { order(:created_at) }\n    # scope :by_role, -\u003e(role) { where(role: role) }\n  end\nend\n```\n\nor if you want to use SQL to create a regular view:\n\n\n```ruby\nclass ActiveUserView \u003c SQLView::Model\n  schema -\u003e { \"SELECT * FROM users WHERE active = TRUE\" }\nend\n```\n\nor the same but materialized:\n\n```ruby\nclass ActiveUserView \u003c SQLView::Model\n  materialized\n  schema -\u003e { \"SELECT * FROM users WHERE active = TRUE\" }\nend\n```\n\nLater with view you can work same way as with any model(ActiveRecord class). For example:\n\n```ruby\nActiveUserView.model.count\n# or\nActiveUserView.count\n# ----\nActiveUserView.find(42)\n# you can apply scopes, relations, methods, BUT add them in extend_model_with block\n\nActiveUserView.model.by_role(\"admin\").count\nActiveUserView.where(role: \"admin\").exists?\nActiveUserView.model.includes(:profile)\n```\n\nIf you need to refresh materialized view - `ActiveUserView.sql_view.refresh` (if you need to do it concerrently - `.refresh(concurrently: false)`.\n\nIt can also be used with your other models:\n\n```ruby\nclass Account \u003c ApplicationRecord\n  has_many :users\n\n  has_one :account_stat_view, class_name: AccountStatViewView.model.to_s, foreign_key: :account_id\n  has_many :active_users, join_table: :active_users_views, class_name: ActiveUserView.model.to_s, foreign_key: :account_id\nend\n```\n\n\nMore examples in this file: `./test/sql_view_test.rb`\n\n## Installation\n\n```ruby\ngem \"sql_view\"\n```\n\nAnd then execute:\n```bash\n$ bundle\n```\n\nAnd use generator. Or you can connect it to existing view with `view_name=`:\n\n```ruby\nclass OldUserView \u003c SqlView::Model\n  self.view_name = \"all_old_users\"\n\n  materialized\n\n  schema -\u003e {  User.where(\"age \u003e 18\") }\n\n  extend_model_with do\n    scope :ordered, -\u003e { order(:id) }\n\n    def test_instance_method\n      42\n    end\n  end\nend\n```\n\n## Materialized view + concurrent update\n\n1. add index\n\n```ruby\n  add_index SomeView.view_name, :user_id, unique: true\n```\n\n2. refresh with parameter\n\n```ruby\n  SomeView.sql_view.refresh(concurrently: true)\n```\n\n3. profit :)\n\n## TODO\n\n- CI with different versions of Rails/Ruby\n- make unit tests works with `rake test`\n- `cascade` option\n- move classes to own files\n- code coverage\n- verify how it works with other DB's\n- check if schema was changed on migrate or schema dump?\n\n## Testing\n\n`ruby ./test/sql_view_test.rb` (because somehow `rake test` not works, not critical for now)\n\n## Contributing\n\nYou are welcome to contribute.\n\n## Credits\n\nI know about and actually using `gem scenic`, which is very nice and I tool some examples from it how to dump view into schema.rb but this gem was created to simplify life and reduce amount of time needed to write SQL to create a sql view.\n\n## License\n\nThe gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).\n\n[\u003cimg src=\"https://github.com/igorkasyanchuk/rails_time_travel/blob/main/docs/more_gems.png?raw=true\"\n/\u003e](https://www.railsjazz.com/?utm_source=github\u0026utm_medium=bottom\u0026utm_campaign=sql_view)\n","funding_links":[],"categories":["Ruby"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Figorkasyanchuk%2Fsql_view","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Figorkasyanchuk%2Fsql_view","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Figorkasyanchuk%2Fsql_view/lists"}