[Rails 6] Using bootstrap with Asset Pipeline or Webpacker

I am working on a sample POC in Rails 6 and came across various articles that shows how can we use bootstrap with Webpacker and host all the js, css and images under /app/javascript folder (Whether we are using app like JS or not).

I am not using this Rails 6 PoC for any JS frameworks (like React) for now. This is my simple web application and I would like to have my javascripts remain at /app/javascript folder and my css and images to stay at /app/assets folder. To summarise, I would like to use both Webpacker (for JS compilation) and Asset Pipeline for CSS and images compilation.

I tried the first approach where Webpacker is handling all the JS, CSS and Images but somehow I dislike the idea and the folder naming convention where everything lies under /app/javascript. For e.g. all css files are under /app/javascript/stylesheets and images are under /app/javascript/images and most importantly I am not building app like javascript. Then I sat down and thought for a while and came up with below points:

  1. If it’s my Web app, why can’t I handover the control (of CSS and images) to Asset Pipeline and let it handle everything like it was doing in earlier versions of Rails.
  2. I am trying to mix the concepts of both Webpacker and Asset Pipeline to achieve what I want — which is incorrect.
  3. How can I Integrate newly integrated Trix editor and add Bootstrap features like Modal/AutoComplete etc. with both?
  4. Let’s say I have 3 types of Users in my PoC (i) User, (ii) Client and (iii) Admin. User and Admin will use the Web App (everything controlled by Asset Pipeline and Webpacker both) and for Client — there will be a React App (controlled only by Webpacker) — Is it possible?

Well enough theory for now. Let’s see some code in action:

1st Approach: Using Asset Pipeline for bootstrap + Using Webpacker for jQuery & Trix Editor + Using Bootstrap – Modal



# Gemfile
gem 'webpacker', '~> 4.0'
gem 'bootstrap', '~> 4.3.1'
gem 'jquery-rails'
gem 'trix-rails', require: 'trix'

# /app/assets/stylesheets/application.scss
@import 'bootstrap';
@import 'trix';
@import './_custom.scss' // this is my customise css

# from console
# $ yarn add bootstrap jquery popper.js trix
# then check package.json to verifiy the same

# /app/javascript/application.js
require("bootstrap/dist/js/bootstrap")
require("trix")
require("jquery")

# config/webpacker.yml
# Uncomment resolved_paths: ['app/assets']

# under config/webpack/environment.js
# replace everything with the content below:
const { environment } = require('@rails/webpacker')
const webpack = require('webpack')

environment.plugins.append(
  'Provide',
  new webpack.ProvidePlugin({
    $: 'jquery',
    jQuery: 'jquery',
    Popper: ['popper.js', 'default']
  })
)
module.exports = environment

# Inside app/views/layouts/application.haml (or ERB whichever)
= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload'
= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload'


With above settings in place you can use bootstrap CSS, bootstrap features like Modal, autocomplete, jQuery (defined in /app/javascript)

The only disadvantage I can see in this approach is – repetitive code. I am using bootstrap, trix and jQuery for Asset Pipeline (via Gemfile) as well as for Webpacker (via yarn)


I am all ears to know, if there a way to deal with this situation

Now what if, we have to add react to it? I will soon publish a second part of this article covering this case.


Happy Coding!

Requests that take more than 60s to complete fails – ElasticBeanstalk

This short post specifically targets:
– RoR as web development environment – Can be ignored as this is closely related to nginx configuration settings
Nginx as web server


While working with ElasticBeanstalk environments, one of my requirement was to send a heavy job to Worker App that takes > 1 min (60 seconds) to complete and I had no configuration in place. The way beanstalk-app was handling that job was disappointing. That job never finishes within a minute and another job (duplicate) gets triggered by the app and this goes on till it reaches the max retry count.

I tried googling the solution and found that we have to increase the timeout for the web server which is handling the request. In my case it was `nginx`.

So I decided to write a config file under `.ebextensions/02_nginx_proxy.config` — I am not going into the details of `ebextensions` here as this is out of scope of this article.

Here’s how my config file looks like:

Here if you focus on lines:
`proxy_send_timeout 600;`
`proxy_read_timeout 1h;`
`send_timeout 600;`

This will prevent sending multiple requests of same job type until the current one finishes in 1h.

If you need any inputs on what other lines are all about/doing, then leave your comment.

Happy Coding!

 

Configure Delayed Job with Elastic Beanstalk

Recently, I got a chance to work with Elastic Beanstalk and trust me, it is not as friendly as Heroku and it took me a little while to get used to with Beanstalk deployments.

I am using delayed_job in my project and the requirement was very simple, i.e. to automate background jobs. On heroku we simply add a worker dyno and jobs start working immediately. But, same is not the case with Beanstalk. I came across with various article where people suggested to add a shell script inside `.ebextensions` but I did not find this a full proof solution. Then my colleague suggested me to try `active_elastic_job` @ https://github.com/tawan/active-elastic-job

I find this gem extremely helpful and the installation instructions are super simple.

In this article, I will not dig into how to configure, install and start using this gem (because if you visit the link, the steps are defined in simplest form and should not block you). My idea, is to highlight/cover the areas which are not mentioned there or missing.

1. When you create a worker environment, skip selecting the RDS section (which means you’ll create your worker environment without a RDS DB).

2. Now you’ll have to use the existing database (which your web environment is using). For that, copy all RDS environment variables from web environment to your worker environment.

3. Once above is done, deploy your the code to your worker environment. In case your deployment fails with reason:


PG::ConnectionBad: could not connect to server: Connection timed out

Then, go to Services ~> Elastic Beanstalk ~> You Web Application ~> Configuration ~> Instances ~> Modify and note down the Security Group there (using new UI of Beanstalk)

Now, go to Services ~> Elastic Beanstalk ~> Your worker application ~> Configuration ~> Instances ~> Modify and check the security group which your Web Application is using (Note that you can check as many as you want) and Save your changes. This should allow your worker app to use the same DB.

4. Once you have successfully deployed and configured your worker app and you get:


ActiveJob::QueueAdapters::ActiveElasticJobAdapter::SerializedJobTooBig
The job contains bytes in its serialzed form, which exceeds the allowed maximum of 262144 bytes imposed by Amazon SQS

That means you are not allowed to send more than 256KB of data to delayed job. This could prove a bottleneck and you’ll have to think of a workaround to deal with this error. Although, folks on internet suggested that we could use Amazon Extended Client Library for JAVA @ https://github.com/awslabs/amazon-sqs-java-extended-client-lib but I wasn’t able to use and apply this in my Rails app.

Having said that, if anyone knows how to use this in Rails, please drop a comment or as an alternate try to send data < 256KB to SOS queue

That’s all I have for now. See you soon! Happy Coding. 🙂

[Ruby]: Update hash values with Array

Hi Folks,

In this small tutorial, I am writing a program that updates value of each element in hash with a given array values.
Given that:
h = { h1: 'value1', h2: 'value2', h3: 'value3', h4: 'value4' }
a = [ '1', '2', '3', '4' ]
Where h is a Hash and a is an Array

Output we would like to achieve here is:
h = { h1: 'value1_1', h2: 'value2_2', h3: 'value3_3', h4: 'value4_4' }

Let’s code it:

h = { h1: 'value1', h2: 'value2', h3: 'value3', h4: 'value4' }
a = [ '1', '2', '3', '4' ]

h.each_with_index do |(k, v), i|
break if a.size > h.keys.size

a.each_with_index { |val, index|
if i == index
h[k] = v.to_s + ‘_’ + val.to_s
end
}
end

p h.inspect
# Output => h = { :h1 => “value1_1”, :h2 => “value2_2”, :h3 => “value3_3”, :h4 => “value4_4” }

I’ve tried to minimize the number of loops here. Appreciate your feedback and suggestions.

Happy Coding! 🙂

Learning RSPEC with Rails 4 (Alpha)

Hi Folks,

Hope you all are fine and doing good! I am sure most of you, are using TDD for years now. And, once we think of TDD, the first thing comes into our mind is, RSPEC. We all agree that Rspec is a great framework of Test-Driven-Development and its integration with other libraries (like fixtures etc.) is seamless.

With rapid revolution happening in Rails community, Rspec too has evolved over the years, and my motto is to bring this newly developed RSPEC framework in such a way so that, those who are eager to learn TDD can take tips and take this as a learning material. And those, who are planning to migrate can refer to this!

Environments I am using:

  • Ruby 2.1.2
  • Rails 4.2.1
  • Rspec 3.2.0

Idea is to share small code snippets while learning these changes, where we see: what is new. So let’s explore this now:

1. In Rspec 3, the support for ‘should‘ (e.g. foo.should == bar) is deprecated and is no longer supported. Instead of ‘should’, rspec encourages us to use ‘expect‘. Let’s see how it works:

If you try running this example, you’ll get this deprecation warning message:

Deprecation Warnings:

Using `should` from rspec-expectations‘ old `:should` syntax without explicitly enabling the syntax is deprecated. Use the new `:expect` syntax or explicitly enable `:should` with `config.expect_with(:rspec) { |c| c.syntax = :should }` instead

 

Now, let’s take an example of controller spec. Create a controller with scaffold and write the spec as below:

I’ll cover model, helper and view spec very soon.

Happy Coding 🙂

[Ruby] Fetching Emails from Microsoft Outlook

Hi Folks,

Hope everyone is fine and doing good. In this article of mine, I am going to narrate, how you can fetch Emails from your Microsoft Outlook account. I am only going to cover ‘Inbox‘ here. However, the scope of library (Gem) is very vast and you can customize this as per your need.

PREREQUISITE:

  • Ruby
  • ViewPoint Gem: gem install viewpoint

For Debugging, I am using viewpoint/logging/config

Hope this helps someone! Keep in touch and Happy Coding 🙂

Puneet

Rails 4: Changeset

Hey Everyone,

I know, I am very late in posting this article, as I didn’t get chance to do much hands-on in Rails 4. But now, that we all are on the same page, let me quickly set the summary here.

Most of us (1) have already started with Rails4, most of them (2) are planning to and most of them (3) are still on Rails 3. So my target audience for this post is #2 and #3. Developers working on Rails4, if they wish to provide any comments/suggestions they are most welcome.

Recently, I got a chance to develop a new application in Rails4. There are many articles available online, which will provide you insight about the changeset in Rails4. But my idea is to give a step by step information, as I continue to work on my existing application. Hence, this post will keep updating at regular intervals.

Folks can take the information from here which is relevant to them.

– If you wish to localize your gems (including Rails4), to your application, you must need to run:

After, rails new {APP_NAME}, then your bundle runs. Once it is finished, run this command:
bundle install --path vendor/gems

This command will create a .bundle folder inside your app. If you open this folder, there is a config file, where path of the gems is defined. You don’t need to define the path again and again. This config file will take care of it.

– If you have a pending migration and you’re trying to browse your application, Rails tells you to do a rake db:migrate before you see you app in action. See attached screenshot for more reference.

Pending Migration Rails4

Including modules in Rails4: If you wish to include any re-usable module in a common place (say application_controller.rb) from your {Rails.root}/lib folder, then you must need to tell your application to load the path. To do this, type:
config.autoload_paths += %W(#{config.root}/lib)

Model.find_or_create_by_{COLUMN_NAMES} is deprecated in Rails4. To use it:
Model.where(col_1: SOME_VALUE, col_2: SOME_VALUE).first_or_create

ActiveRecord::Relation is now changed to #<ActiveRecord::Associations::CollectionProxy []>

– using of conditions while defining associations is no longer supported. Till Rails 3, one can use this syntax:

– Adding Stylesheets: If you’re trying to add any stylesheet into layout, You must need to add it under ‘config/initializers/assets.rb’
Rails4 shows it in a very beautiful way (refer to the attached screenshot)

assets handling in rails4
assets handling in rails4

ActionMailer: deliver_now & deliver_later: Action Mailer is now integrated with Active Job so that you can send emails outside of the request-response cycle, hence the user doesn’t have to wait for the request to complete.

However, if you wish to send the mail straightaway, use deliver_now.

UserMailer.welcome_mail(@user).deliver_later
UserMailer.welcome_mail(@user).deliver_now