{"id":15463149,"url":"https://github.com/cxspxr/react-shortener","last_synced_at":"2026-02-17T09:43:45.114Z","repository":{"id":40307796,"uuid":"150496401","full_name":"cxspxr/react-shortener","owner":"cxspxr","description":":link: Rails API \u0026 React URL Shortener","archived":false,"fork":false,"pushed_at":"2025-03-03T11:57:47.000Z","size":405,"stargazers_count":1,"open_issues_count":13,"forks_count":1,"subscribers_count":0,"default_branch":"api","last_synced_at":"2025-07-20T09:34:58.863Z","etag":null,"topics":["coffeescript2","heroku","jsx","postcss","rack-attack","rails","rails5-api","react","reactjs","rspec","stylus","sugarss","url-shortener","webpack"],"latest_commit_sha":null,"homepage":"https://shorrtener.herokuapp.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/cxspxr.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2018-09-26T22:15:58.000Z","updated_at":"2020-06-16T15:37:51.000Z","dependencies_parsed_at":"2024-06-21T11:07:33.754Z","dependency_job_id":"3bd9d739-180f-4ed7-bfe6-ef7419a885c0","html_url":"https://github.com/cxspxr/react-shortener","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/cxspxr/react-shortener","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cxspxr%2Freact-shortener","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cxspxr%2Freact-shortener/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cxspxr%2Freact-shortener/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cxspxr%2Freact-shortener/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cxspxr","download_url":"https://codeload.github.com/cxspxr/react-shortener/tar.gz/refs/heads/api","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cxspxr%2Freact-shortener/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":271746777,"owners_count":24813583,"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","status":"online","status_checked_at":"2025-08-23T02:00:09.327Z","response_time":69,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["coffeescript2","heroku","jsx","postcss","rack-attack","rails","rails5-api","react","reactjs","rspec","stylus","sugarss","url-shortener","webpack"],"created_at":"2024-10-02T00:07:28.533Z","updated_at":"2026-02-17T09:43:45.073Z","avatar_url":"https://github.com/cxspxr.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# :postbox: Rails API for URL Shortening :outbox_tray:\n\nWhat I'm gonna use:\n\n* [Rails](https://github.com/rails/rails) API 5.2.1\n\n* [MySQL2](https://github.com/brianmario/mysql2)\n\n* [RSpec](https://github.com/rspec/rspec-rails) for testing\n\n* [Shoulda Matchers](https://github.com/thoughtbot/shoulda-matchers) for simplier `RSpec` testing\n\n* [Faker](https://github.com/stympy/faker)\n\n* [Heroku](https://heroku.com/) for deployment \u0026 development\n\n* [Husky](https://github.com/typicode/husky) to manage GIT hooks \u0026 to run `RSpec` test on `pre-commit` \u0026 `pre-push`\n\n* [Rack::Attack](https://github.com/kickstarter/rack-attack) to prevent DOS\n* [Rack CORS](https://github.com/cyu/rack-cors) for Cross-Origin Resource Sharing\n\n* [Memcached/Dalli](https://github.com/petergoldstein/dalli) for requests throttling\n\n* [Geocoder](https://github.com/alexreisner/geocoder) to track locations\n\n----\n\n## Development\n\nUse `rails s` and [curl](https://github.com/curl/curl) for HTTP requests.\n\n---\n\n## Deployment\n\nThis might be deployed as an isolated API as it is shown [here](https://rails-shortener.herokuapp.com/api/links/count) (this **exactly** route returns the current number of links for `base62` encoding). Along with a frontend like [this](https://vue-shortener.herokuapp.com/) ([git](https://github.com/cxsper/vue-shortener) for it) served with some http server. Just don't forget to respect the `CORS` as it is shown [here](https://github.com/cxsper/react-shortener/blob/api/config/application.rb#L40).\n\nOn the other hand it could be deployed as a part of  monolithic system as it is shown [here](https://shorrtener.herokuapp.com/) ([react branch](https://github.com/cxsper/react-shortener/tree/react) of this repo) with a `Puma` for http serving.\n\n---\n\n## Project Structure\n\n### `app/`\n\nYou may know the `app/` structure since it's pretty default. It's the home to `models`, `controllers`, `validators`, `exception handlers` etc.\n\n#### Controllers\n\nThere are three controllers which are interesting for us:\n* `application_controller` with module dependencies;\n* `links_controller` handles `store`-ing, `get`-ing, `count`-ing for the `Link` model;\n* `redirect_controller` with a single method to `redirect` and store the `Redirect` itself (i.e. it's location) using the [Geocoder](https://github.com/alexreisner/geocoder);\n\n#### Models\n\n* `Link` to store `:url` and `:shortened`;\n* `Redirect` to store `:location` and `:time`;\n\nA single `Link` has many `Redirects`. A single `Redirect` belongs to one `Link`.\n\n#### Validators\n\n* `Base62Validator` to `validate :base62` shortening;\n* `UrlValidator` to `validate :url` formatting;\n\n### `config/`\n\n* `initializers/rack_attack.rb` to configure [Rack::Attack](https://github.com/kickstarter/rack-attack);\n\n* `environments/*.rb` to manage heroku `production` and local environments (`development` and `testing`);\n\n### `spec/`\n\nThis is for [RSpec](https://github.com/rspec/rspec-rails) with [Shoulda Matchers](https://github.com/thoughtbot/shoulda-matchers) \u0026 [Faker](https://github.com/stympy/faker) testing.\n\nI belive that everything is backed by tests by now.\n\n### Specific files\n\n`.branch-ignore` is used by me to manage branch-specific `.gitignore` using [Husky](https://github.com/typicode/husky) and `.gitignore.\u003cbranch-name\u003e` files.\n\n### `/.*|(other)/` folders \u0026 files are pretty default\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcxspxr%2Freact-shortener","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcxspxr%2Freact-shortener","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcxspxr%2Freact-shortener/lists"}