Using ActiveStorage with DropZone in a React app

The last year or so I have been working on an app for teaching programming that I hope to release in a few weeks. The CMS for the app is a React based web app powered by a Rails server. The Rails server is running in an API-only mode which has been working out reasonably well.

One of the recent additions to Rails has been the ActiveStorage system that purports to make attaching media to Rails models really simple. Unfortunately most of the documentation around it involves using Rails’ View tier as well which the API-only mode strips out. In fact, getting there is an open bug on ActiveStorage to actually make it work out of the box in API-only projects.

Oh and one more thing: ActiveStorage doesn’t support uploading to multiple buckets, just in case thats a dealbreaker for you.

After a couple of days of struggling through it, I finally have it working in an API only mode using the React Dropzone Component instead of a boring filepicker.

Also note, there is an open source React component for interacting with ActiveStorage which I did not try, mostly cause I was already halfway done with the Dropzone implementation by the time I discovered it.

Issue #1: ActiveStorage CSRF errors in API only mode

ActiveStorage ships with a JavaScript library that does a lot of the work, but one of the issues with using ActiveStorage from a react app was that it tries to do CSRF token validation on the requests but cannot. To solve it, I added a initializer in the initializers folder that skipped CSRF checks for it

ActiveStorage::DirectUploadsController.instance_eval { skip_forgery_protection }

Issue #2: Cors challenges

So this isn’t a bug but when working on a React app using the CreateReactApp project, the React app runs on port 3000 while the Rails server runs on port 3001. To prevent CORS issues when uploading images, I had to add the Ract::Cors gem and a cors initializer that allowed requests from localhost:3000 during development

Rails.application.config.middleware.insert_before 0, Rack::Cors do
 allow do
   origins 'localhost:3000'
   resource '*',
    headers: :any,
    methods: [:get, :post, :put, :patch, :delete, :options, :head]
 end
end

Also, since the React app was using DirectUpload to S3, you have to add the right Cors settings for your S3 buckets as well (this blog post helped figure out the CORS issue)

Uploading an Image using React and Dropzone:

The core part of the image uploader component is below:

const url = '/rails/active_storage/direct_uploads'
const upload = new DirectUpload(file, url, this)

upload.create((error, blob) => {
 if (error) {
    console.log("Image Error:", error)
 }
 else {
    this.dropzone.removeAllFiles(true);
    this.props.onImageUploaded(blob)
   }
})

The DirectUpload class comes from the ActiveStorage JavaScript file. When this code is run, the image is uploaded to the storage provider and you get back a blob (just a JavaScript hash)  with a bunch of metadata (that is saved in the `active_storage_blobs` database table.

One of the keys in the hash is called signed_id. To assign the uploaded image as an attachment to any of the models, the model has to have a has_one_attached or a has_many_attached field. In my case its something like

class Book < ApplicationRecord
  has_many_attached :images
end

 

In my book controller I can then accept a PUT request that updates the record like so:

@book.images.attach( params[:signed_id] )

or better yet just let strong_params do it automatically.

 

 

Using Symlinked Node libraries with React Native 0.55

I recently updated the React Native app I have been working on for a while from RN 0.47 to 0.55. I’ll admit I was a bit callous about the update and hadn’t really looked at the change log, but hey, version control does give one a foolish sense of bravado.

Anyway, needless to say there were issues. As of RN 0.55.4, the `setJSMainModuleName` has been renamed to `setJSMainModulePath` and it took me a bit of sleuthing to figure that out (Find the Github commit here)

However a bigger issue came up when I tried to package the app after resolving the compile errors.

Screen Shot 2018-05-16 at 1.19.27 AM

Turns out the new Metro packager cannot follow symlinks, like those created by npm-link

This was a total fail for me, since my app uses local npm modules to hold pieces of common code for the web and mobile clients.

Thankfully someone did come up with a bit of a hack that generates absolute paths for all symlinked libraries and launches the cli.js file of the packager with a config file with the list of absolute paths.

It works for now, but hopefully this bug will get fixed soon.

Helios: Visualizing TechCrunch data with OpenFrameworks


Helios ScreenshotOnce a quarter, the Technical and Product Team at Comcast lets all its engineers participate in a “Lab Week”, a tradition that started a while back at CIM and now encompasses a much larger Engineering group across Comcast. Goals of labweek can be different, from learning new technologies to pitching new products and services. You can read a bit more about lab week here

This quarter, I (and Gabo by coercion) decided to work on a data visualization project, mostly as an excuse to learn OpenFrameworks. For the unfamiliar, OpenFrameworks is a C++ based toolkit for “creative coding”. Its used quite a bit in a variety of fields visualizing information or just creating very rich visual imagery. For example, it was used in Tron:Legacy for creating a variety of visuals used in the movie. Being in C++, it gives you so much power and its really nice not really worrying about how many pixels/shapes you are putting on screen. The other thing thats really cool is that its cross platform and your C++ code is compiled to OpenGL based desktop apps or OpenGL ES based Android or iPhone apps.

The app itself was interesting: At my current group, Comcast Innovation Labs, we work quite a bit with startups but often I am very unfamiliar with their history. So the goal of the app was to represent the startup data and see how they compared with their competitors.  We never finished our final vision, but the app as it stands currently lets you plug in names of companies and the app will render them on the stage with circles representing the size of their funding on a timeline of when they did close their funding rounds as well as any news stories that mentioned them in that timeframe. You can see a video of the app in use below:

 

 

We went from barely remembering C++ and reading up on OF to the project shown below in 4 days. The code is not super clean and there are is also a lot of code that we ended up not using thats in the codebase, but if its on GitHub if you want to take a look. And if you want to install the app just to check it out, you can download it from here

Yatr: Our hack for the Techcrunch NYC Hackathon

This weekend Gabo, Rob and I participated at the Techcrunch Disrupt NYC Hackathon, a 24 hour coding event where you come out the other side with some product. We decided to make a comments/conversation engine with some interesting twists named Yatr.

Why Comments?

It took us quite a while to reach a decision (actually till about 30 mins before the event) on what we would build. Comments are interesting for a couple of reasons.

  • Comments are really important but mostly neglected in the social world. If you look at the apps space, there are a million “link farming” apps that grab the top stories from your Twitter stream and yet there arent much that bring out the conversations around them.
  • A lot of blogs disallow comments completely (usually citing low signal to noise ratio).
  • Conversations often tend to get too specific: For example, a conversations around “iPhone4” are interesting to people who have Android phones. It would be great to surface these products up into a “phones” conversation. Even better, I’d like to subscribe to the top conversations around phones
  • I had been reading a lot of posts like this: https://drumbeat.org/en-US/challenges/beyond-comment-threads/
  • We wanted to blur the line between comments and content (blog posts). Yatr comments were supposed to be embeddable and a subaccount could be used as a blog engine on its own.

The Hack:

Our hack (video below), involved a bookmarklet that allows you to comment on any link. This comment can be shared to Twitter but also gets added to our database. Additionally we used a Readability library to find the relevant content on the page and then a term extraction library to find the main words in the post to try to find the appropriate tags (additionally I would like to use a clustering algorithm to improve the context recognition system). When a comment is made, we add that to all the relevant topics we can find.

On the other side, we created unique pages for each of the items commented upon, both the links specifically and also the tags on the content. The pages get pretty interesting where we Embed.ly ( and in the future DuckDuckGo‘s zero click API) to add more information to the page. The video below for example takes you from the link about “Portal 2” to the tag page with a bunch of popular links around Portal 2.

The whole App was written in Sinatra. I am a Ruby noob so I had been looking for a project to play with some middleware/Ruby. A big part of my goal for the hackathon was to learn using a new technology and I definitely came out of that pretty educated.

We had a lot of ideas on what this could/should be (actually all 3 of us had different ideas on what we wanted it to be, it didn’t help that all of us have very different opinions on social networking 😉 ). I am hoping to fix a bunch of things before putting it online, even if just for kicks.

P.S: Also check out Rob’s post on the event. He has photos and stuff!