{"id":19063247,"url":"https://github.com/delner/gifme","last_synced_at":"2025-07-28T10:36:38.945Z","repository":{"id":151360045,"uuid":"50804785","full_name":"delner/gifme","owner":"delner","description":"A sample React/Rails application.","archived":false,"fork":false,"pushed_at":"2016-02-01T03:18:29.000Z","size":361,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-02-22T02:41:16.371Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/delner.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}},"created_at":"2016-02-01T01:14:07.000Z","updated_at":"2016-02-01T01:14:39.000Z","dependencies_parsed_at":"2023-04-23T23:54:32.033Z","dependency_job_id":null,"html_url":"https://github.com/delner/gifme","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/delner/gifme","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/delner%2Fgifme","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/delner%2Fgifme/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/delner%2Fgifme/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/delner%2Fgifme/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/delner","download_url":"https://codeload.github.com/delner/gifme/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/delner%2Fgifme/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267503392,"owners_count":24098328,"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-07-28T02:00:09.689Z","response_time":68,"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":[],"created_at":"2024-11-09T00:29:22.775Z","updated_at":"2025-07-28T10:36:38.896Z","avatar_url":"https://github.com/delner.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# GIFME\r\n### *A ReactJS + Rails application example*\r\n###### *For Rails 4.2, Ruby 2.3.0, ReactJS 0.14.3*\r\n\r\n### Introduction\r\n\r\n*GIFME* is an application that mimics everyone's favorite GIF search engine, [Giphy](http://giphy.com/). It uses the Giphy API to search and view for relevant GIFs.\r\n\r\n### Requirements\r\n\r\n - Ruby 2.3.0+\r\n - Rails 4.2+\r\n\r\n### Installation\r\n\r\n1. Install Ruby 2.3.0 via your favorite package manager (RVM, Homebrew, etc)\r\n2. `gem install bundler`\r\n3. Clone this repository into a folder of your choice\r\n4. `bundle install` to install all dependencies\r\n\r\n### Run GIFME\r\n\r\n1. `bundle exec rails s -b 0.0.0.0` to start a webserver\r\n2. Access the website via `http://localhost:3000/` or your IP address/DNS name.\r\n\r\n### Using GIFME\r\n\r\n##### Searching\r\n\r\nThere is search bar on the top of every page: enter any phrase and press *Enter* or click the search icon to perform a search.\r\n\r\n##### Reviewing matches\r\n\r\nSearching will bring you to a search index page, where you can see thumbnails of relevant GIFs. Hover over them to see them animate, click them to view.\r\n\r\n##### Viewing a GIF\r\n\r\nThe view page will show the original size GIF constrained to the viewport. It will also show some attributes about the image clicked on.\r\n\r\n##### Find a random GIF\r\n\r\nOn the GIF view page, you can click the random button. It will redirect you to another random GIF from the results of the phrase you originally searched for.\r\n\r\n### Testing GIFME\r\n\r\nYou can run some unit tests with `bundle exec rspec`.\r\n\r\n*NOTE: In it's present state, most of the interesting code is in Javascript (React components) which is not covered directly by Rspec. Ideally, given more time, there would be some basic integration tests driven from either Jasmine or Rspec/Capybara to test the core requirements.*\r\n\r\n### Changelog\r\n\r\nWhile developing the project, I focused on a rapid prototype scheme, since I was working with new, unfamiliar tech (in this case, ReactJS), and wanted to see it work before I committed to it.\r\n\r\n###### First I did the initial setup...\r\n\r\n1. Created a set of mockup images of what each view should look like when done, at each browser size.\r\n1. Initialized Rails application and installed dependencies (ReactJS, FontAwesome, etc)\r\n2. Added controllers and routes for each view (`home#index`, `search#index` `search#view`)\r\n\r\n###### Then I focused on making the basic behavior work (albeit ugly)\r\n\r\n1. Added React components for each view, unstyled (`ImageList`, `ImageThumb`, etc...)\r\n2. Wired up API calls to Giphy from components.\r\n3. Added hover state, random button, and search bar components.\r\n4. Clicked through the barebones site, verified that functionality worked.\r\n\r\n###### Now that the core feature set was working, time to make it look nice\r\n\r\n1. Established my constants and breakpoint sizes for my responsive scheme (colors, widths, etc)\r\n2. Started by adding my application wide styles (logo, search bar, etc), working my way from mobile to desktop-level styles. Rudimentary testing by changing my browser width to trigger breakpoints.\r\n3. Then added styles for my search results grid.\r\n4. And then added styles for the view page.\r\n5. Once things looked okay in my browser, it was time to do some device testing\r\n  - Started with Chrome/Firefox on my MS Surface Pro\r\n  - Then tested Chrome on Android\r\n  - Then borrowed an Apple laptop and iPhone to test Safari and various orientations.\r\n  \r\n###### It's starting to look pretty good. Time to polish a bit\r\n\r\n1. Refactored my API and Routing calls into a couple of classes using the JS Class pattern. It makes them more modular, and abstracts some detail from view components that shouldn't care about these sorts of things.\r\n2. Added a search icon to the search bar (to signal to the user its purpose)\r\n3. Added a loading spinner and CSS animation that appears if the API call is taking a while (doesn't happen often.) You can see it by commenting `.loading { display: none; }` in `layout.scss`.\r\n4. More device testing (mobile Safari didn't like the search icon much)\r\n5. Add some documentation\r\n\r\n###### Ship it!\r\n\r\n### Let's talk about design...\r\n\r\nMaking prototypes and demos requires balancing your needs, aspirations, and resources into a practical compromise. This project was no exception: so let's talk a little bit about how I made my compromises.\r\n\r\n**This application needs...**\r\n\r\n - To fulfill a set of some pre-defined features. Although I granted myself some creative license, the spirit of the core feature need to work as described.\r\n - Needs to be fast \u0026 lightweight.\r\n - Needs to be done fast. (1 week requirement.)\r\n - Needs to work well on all devices.\r\n \r\n**My aspirations were to...**\r\n \r\n - Make a clean, uncluttered design\r\n - Try some new technology (Angular, Ember, or ReactJS)\r\n\r\n**And my resources included...**\r\n\r\n - 6-8 hours over a long weekend (this was written while on the road, in my free time)\r\n - A laptop running Ubuntu to code with, and an Android phone (and family's Apple devices) to test with\r\n - My experience building traditional Rails apps \u0026 APIs with SASS, HTML5, and \"vanilla\" JS (I haven't used single-page frameworks or ReactJS before)\r\n \r\n ###### Some options at my disposal...\r\n \r\n I thought about 3 different ways of building this prototype:\r\n \r\n 1. **Traditional Rails app**: serving each view directly from a web server, and compiling all HTML, CSS on the backend, then using some jQuery to piece together some JS-specific functionality.\r\n  - I'm very familiar with this tech, and it's pretty quick to build.\r\n  - But given a lot of the data was driven from an external API, there could be some performance drawbacks or weirdly handled architecture choices to accomodate for this.\r\n 2. **Single-page framework**: use Rails to serve single-page framework assets to user, then use their browser to handle all routing \u0026 rendering.\r\n  - The application, since it lives off of an external API, could live purely in the browser. It'd be super light-weight and fast: awesome!\r\n  - ...but I've never used Angular/Ember, and I'm under some time constraints. There are some risks pursuing this now.\r\n 3. **View framework**: use Rails + React to deliver my UI components instead of using Rails to render lots of HTML/SASS.\r\n  - This would make the application a bit more flexible/structured in JS. Cleaner API implementation, too.\r\n  - ...I've also never used it before. But its only the view part of \"MVC\" that would be new.\r\n  \r\nAlthough I was very familiar with **Option #1**, it has too many drawbacks, and just doesn't feel like a good fit: so I ruled that out immediately. So I focused on **#2** and **#3**. Ultimately, given my time constraints, I decided option **#3** was a better compromise between my needs and resources. I watched a few videos and ReactJS and it seemed like a less risky proposition, while still making the application a bit lighter, and affording an opportunity to go full-bore SPF if I found myself with extra time.\r\n\r\n##### Some other thoughts\r\n\r\n - In order to support a variety of devices, I decided to focus on a mobile-first responsive design approach. Using CSS \u0026 non-device-specific media queries, I implemented each view around a set of breakpoints, which allowed me to quickly and easily accomplish some nice designs with minimal device-specific work. Check out `layout.png` to see an early mockup of the design I aimed for.\r\n - For a production deployment, I envisioned leveraging a CDN (like Cloudfront) to deliver most of the pre-compiled assets quickly to the user. If time had permitted, and a SPF could have been implemented, it was conceivable that the entire application could have been served in static form from CDN, removing the need for a web-server entirely allowing it to scale wide and cheap.\r\n - I had plans for encapsulating the web-server in a Docker container, something that would have made installation really easy. Unfortunately, given the limitations of the laptop I was working on, I did not have the capability to set up a Docker container with `docker-compose` (something I would have done on my home desktop.) So for now, it requuires a manual setup of Ruby to run.\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdelner%2Fgifme","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdelner%2Fgifme","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdelner%2Fgifme/lists"}