Rails bulk delete items on frontend part

So when your database grows it might come in handy if you give your customers the option to bulk manipulate data in lists. I’ve got a list of products and my client told me, that they often create dozens of test items to check out things and then they delete them. Clicking one by one and, especially, waiting every time for the page to load can be tiresome. Here is my approach:

Wrap the listing table in a form

Don’t get confused by my ‘object’… err… object, it serves the purpose of enabling many models to use this listing partial. The main parts are ‘form_for’, the checkbox and the ‘submit_tag’. It is important to use an array for storing the checkbox values, or else we won’t be able to retrieve all id’s at once.

Now the form leads us to the custom controller (‘rails g controller bulk_actions’):

First of all, I’m getting the object from ‘params[:object]’ (this is why I included the hidden_field_tag in my form). Since I’m using the partial for any model, I need to know, do I delete the Post model or the Product model right now. The if-clause makes sure we only handle a bunch of items, it does not make any sense to bulk delete 1 item. Since my object is rather a string, I need to convert it to a modal constant. Then we simply iterate over each found object and destroy it. You can disregard the ‘sublevel’ part.

Now for the frontend – I wanted the delete button only to appear if two or more items are selected and be hidden elsewise. Since I’m using iChech checkboxes we need to hook up on different methods. Particularly it is ‘ifToggled’ in this case:

Add one last thing – the route

And you are ready to go!

Heavily inspired by this article.

SSL for Ruby on Rails app

When pummeling around this problem I figured out there are not many step-by-step tutorials for dummies (like me). So after fixing all issues, I think it’s good practice to share the knowledge.

How to set up SSL for your rails application

Step 1: Obtain the SSL certificate. Various providers offer them. A certificate is, simply put, a bunch of text. It is divided into few parts. Usually two or four. The first one is the key. The second one is the actual certificate. It might be split into three separate files.

Step 2: Place those files on your server. I put them inside the Nginx directory (/etc/nginx/ssl/project_name/certificate.crt – for the certificate and /etc/nginx/ssl/project_name/certificate.key – for the key) Be sure, to concatenate your certificate the right way. If it’s not concatenated yet, take care of combining them together with, the right way – there is always a middle part, a prefix, and a suffix part. Putting middle part at the end will cause the file to malfunction.

Example of the certificate file

Step 3: Configure Nginx. My example is listed below. It shows how you can run both versions, http and https at the same time. Additionally, I included a redirect, so my client doesn’t need to buy certificates for each similar domain.

I’m almost sure that this is the most basic and ineffective approach, but it’s working quite well.

YCMS – first development friendly CMS on Ruby on Rails

Always wanted to bootstrap your application really fast, but considering ActiveAdmin or RailsAdmin was a pain because of their limited flexibility? Now, with YCMS you don’t need to worry anymore. This CMS is as simple as it could ever be. No mountable Engines, not gems, simply git clone this application, rename your databases and you are set up and ready to go. My ruby on rails cms is customizable just as every normal app you would write from scratch. There is no hidden DSL, special methods or other stuff. You need a new model, you simply add it as you would to your own application.

Features:

  • Already included models for: posts, pages, page/post-categories, users
  • User management via Devise gem
  • Base settings available
  • Assets, views, controllers are split up into front and admin part.
  • Heavily DRY – all common CRUD methods are managed via a controller concern. There is only one form for each model, still perfectly clear and manageable via partials
  • Supported internationalization from the box
  • Controller, model and feature tests.
  • For I18n tests I am using i18n-task gem
  • Human readable routes

Please check it out on GitHub – https://github.com/mohnstrudel/ycms

Fork, contribute, enjoy!

Continuous Integration with Rails, Github and TravisCI

After 25 failing builds I finally managed it! My app works just fine with continuous integration provided by Travis CI.

Here my travis config using postgresql for test environment:

Happy testing!

Create a search…then speed it up by a factor of 50!

One great way to implement a basic search is to put all your data fields into one big array and then perform the search on this one field. Let’s say, you’ve got a Customer model. Open up customer.rb (in app/models/) and write this few lines of code:

To pick only the searched items we’re creating a scope to which we’re passing the search argument. You can add a function, which will turn all separate fields into one big keywords array.

Now, open up your Controller (CustomersController.rb)

If desired, you can add some validation for cases if no search parameter is provided.

This approach won’t yield you amazon like results, but can bring one pretty far.

Step up the game

If you want to make one little step further and do not want to bother with “heavy industry” tools like ElasticSearch, then you can utilize PostgreSQL’s awesome built in indexing features. This approach requires a bit more setup, than the first one, but once you follow those steps, it will appear straight forward.

The main goal is to write our custom SQL query. In the end what we want to achieve is something like this:

Using rails syntax this would mean we need a query like this:

To create this query and keep things clean I’m using an extra class (models/customer_search_term.rb):

Now we need this helper function, “build_for_name_search” (I’ll omit the first one for now).

This function does nothing else rather than building the string for our SQL query. You can verify it by examining the variables – @where_clause is a string, while @where_args is a hash.

Finally, let’s build our controller:

We’re almost there. This search works, but it’s still a bit slow (see below for speed results).

Now we need to create custom indexes on those tables. We will stick to old up and down migration methods, since rails won’t understand our custom SQL migration if we’d stick to “change”.

It’s important to use “varchar_pattern_ops”, since we are not using an exact match, but instead using a like operator. Now, if we fire up rails dbconsole and perform  EXPLAIN ANALYZE on both methods, we can see the difference.Ama

This was the original result:

After spicing things up:

This is an increase by a factor of 243!

Create reusable form partials in Rails

If you’ve got an admin part in your rails app and some settings to take care of, chances are that you have a lot of similar data. And what can be more wearying, than creating all those forms, index/edit/new views over and over again? Of course you could use the scaffold, but I personally strongly dislike it.

So I figured out I try to make my partials variable as possible. This post shows you how you can create highly reusable form partials.

My structure is as following:

There is an admin panel. Inside admin panel there are settings (which get repetitive) and inside settings you can manage models like “colors”, “patterns”, “fabric” (you can guess it – it’s a clothing online shop). All of them contain identical data, but have some differences as well.

I’ve got only 3 views – index, edit and new, because there is no sense for having a show view, as it should be the edit view right from the get go. This said, we need only two partials – one, for listing items inside our index view and one for creating and editing existing data.

Let’s start with routes.rb:

Simple dashboard when you visit plain old “/admin” and then resources inside another namespace “settings”.

My index view – index.html.haml:

As you can see, I pass 3 local variable to my partial (this is the only thing you need to edit for each model. But hey, it’s only 3 words!) – the russian name, so I can have some customized buttons and links. The current collection and the name in english.

Listing items partial (a.k.a. index)

Well, apart from some html, the important things are:

  • to check if there is at least one item in the collection (remember, we pass the collection under the name “current_objects”)
  • for each object in current_objects we access it using the variable “object”
  • since our partial is variable we can’t use hardcoded paths, like “admin_settings_colors_path”. Meaning we must make use of the “send” method, which basically makes a method from a string. To pass parameters to a method created by “send” you simply put this parameter as a parameter to the send-method.  send("hello_there", caramba) is equivalent to calling method hello_there(caramba)
  • Because “object” is actually an object (wow!) we can’t use it in the path generation. This is why I pass “single” as a local variable. “Single” is simply the singular form of the model (category, color, pattern etc.)

My edit/new view:

They are absolutely identical.

I render some flash messages to tell users about successful or failed actions. Then I render my second partial using again a local variable to transmit the collection.

Form partial

The core 🙂

Well, again a lot of HTML, but I will summarize the core points for you:

  • First of all we build our form using triple nesting  =form_for [:admin, :settings, current_objects] do |f|
  • Now comes the most interesting part – surely your models will differ a bit. Maybe on has images to upload, the other doesn’t. One has a price tag, other don’t. Etc. and so on. Thus, we need to create an all-purpose-form, disabling fields when not required. This is done by  respond_to? method. You can see it in this line   -if current_objects.respond_to?(:picture) This basically means, that if there is no :picture method for current object, the block below won’t be executed. Nifty, eh?
  • In my example every model has a field, called “name”, this is why I don’t check for it. All other fields are encapsulated in a respond_to? check.

Resume

With just a few methods – send and respond_to? you can create highly reusable partials where your maintain effort goes towards zero. Only one file for each action (index and edit/new) – truly amazing!

Bitrix 24 REST API

It is quite possible, that none of my visitors will ever stumble upon the Russian CRM system called Bitrix, however if you are one among the unluckiest people, this article might be useful for you. More specific, I will cover how to work with the cloud solution, Bitrix24 and its REST API. There is almost no clear documentation, thus, I think a complete resource might come in handy some time.

Getting started

So what exactly will we be doing? We will connect a web application to an existing bitrix24 portal. Possible use cases are:

  • Upon registration on your web application you want to create a lead inside the CRM
  • Upon completing an order you want to create an order inside the CRM
  • etc.

First and foremost you need to register yourself as a developer at bitrix24 marketplace, there are a lot of links leading to different sub-pages of 1c-bitrix.ru, you’ll need this one: https://marketplace.1c-bitrix.ru/about/for-dev/become.php. Don’t worry, you won’t need to fill out papers as required for a partner account. Just a regular one will do, I think it’s called a ‘technological partner’.

Create your app

Next step is to create your app on marketplace. I don’t like calling it an app, because it collides with our web app, so let’s call it a container for our web application. When logged in as a technical partner, visit this page: https://partners.1c-bitrix.ru/personal/b24marketplace/

There you can register a container. Detailed on screenshot – http://take.ms/xNU1o

  1. Is my status (technical partner)
  2. Menu, where you can find the required link
  3. The actual button you need to press to create a new container

Check all those checkboxes – http://take.ms/FSujv

After creation you can click on your app container (most likely you’ll have just this one – recently created – in the list) and then you should see something like this: http://take.ms/osom0

client_id and client_secret is what’s important.

Attention!

Do not forget to create at least one version! There you can type in a url for callbacks, it’s important for proper functioning aswell. Check out the screenshot: http://take.ms/fCoZC

Managing bitrix24

Now comes the tricky part – we need to authorize your web app inside the bitrix24 portal. To do so you need to contact the administrator of bitrix portal.

If you are yourself an admin it gets a bit easier. Just visit “add an app” – http://take.ms/To7hP and click on “for personal usage”.

Check “API use only” and at least CRM in the long options list. In the marked field we need to provide the url we typed in in the versions tab at marketplace website (http://take.ms/is5ekP)

After adding your app container to your Bitrix24 portal you’ll obtain new client_id and client_secret, just like here – http://take.ms/x4qxr. Only use them from now on! You won’t need any tokens from marketplace.

Last part is to obtain refresh and access tokens. This might be quite cumbersome due to the fact, that you’ll need to retrieve a “code” parameter which lives only 30 seconds. It’s not a big deal if you use some written program for all this stuff, but you can do it by hand as well.

Now open two tabs. Type in the first one (don’t hit enter yet!) – https://your-portal-url.bitrix24.ru/oauth/authorize/?response_type=code&client_id=<ENTER CLIENT ID FROM BITRIX PORTAL HERE>&redirect_uri=<ENTER URL FROM MARKETPLACE PAGE>

Type in the second one (don’t hit enter yet!) – https://your-portal-url.bitrix24.ru/oauth/token/?grant_type=authorization_code&client_id=<CLIENT ID FROM BITRIX PORTAL>&client_secret=<CLIENT SECRET FROM BITRIX PORTAL>&redirect_uri=<ENTER URL FROM MARKETPLACE HERE>&scope=<your-scope>&code=<LEAVE EMPTY AS OF NOW>

Input every variable without <>. Now hit enter in the first tab. You will be redirected to another URL where there will be a code parameter (with a value). Copy that value and insert it in the corresponding place in the second tab. Hit enter again. Now you should receive the desired tokens. Keep them safe!

Tokens

Refresh token is valid for about a month. It is wise to store it in your database with a separate created_at date point. Upon expiring hit the url

You will receive a new refresh token. Answer will look like this:

Same process goes for access token, with the only difference that it expires every hour. So you should check if the creation date was larger than 3600 seconds, and if yes, call the same url. You can separate those two refresh methods or call them all at once and update both tokens every time.

The fun part

Now you surely want to interact with the data from your Bitrix24 portal, right? You’ve made all the way down for this one reason. There are several methods (I will be covering only the CRM part, no calendar etc.).

The general url is following:  https://<YOUR BITRIX PORTAL>.bitrix24.ru/rest/<METHOD NAME>.<TRANSPORT TYPE>&auth=access_token&<PARAMETERS>

Examples

Get all leads

https://your-portal-url.bitrix24.ru/rest/crm.lead.list.json?&auth=uoefoqa8mridzaapux6ja649jbo621xq

Post a new lead

Please be careful as there are no quotation marks allowed. If there are whitespaces inside your data, make sure to use %20 instead. If you are using cyrillic data, make sure to encode it to stuff like this: %D0B3%D1B10 (in rails I do it by using URI.escape –  encoded_name = URI.escape(name) )

Post a new deal

Searching (and filtering)

Please note, that the filter method only searches from the left side, i.e. if the number in the Bitrix 24 portal is as following: 8 903 227 88 74 and you search for 8874 you won’t find anything. You need to start from the left, meaning searching either 8903 or 8903227 or even the full number. It also matter how the phone number is stored inside Bitrix (that’s some crazy bullsh*t, I tell you), because you need to check for all number formats,

8 903 227 88 74
8-903-227-88-74
8 903 227-88-74

Are all different numbers for the filter method.

Last, but not least you can specify the output with “select” chaining. In my example I’m grabbing ID, Name and Last_Name from all possible fields.

Everything else

It is highly recommended to create a new portal for testing, then install the documentation app. It has a console built in where your can look up all the remaining methods and url calls. Simply hit the “run this code”, then click on the “post” tab – http://take.ms/GH5hM

Scroll down. There you should thee the complete url from the example – http://take.ms/vnU3i

Conclusion

Working with Bitrix24 REST API is far away from being easy like working with Twitter or Instagram API. However you can still do it. I hope my guide will help one lost soul out there. I’m planning on writing a gem for Ruby on Rails which will do all the ugly work for you. It should be out on the githubs around winter 2016/2017.

AbsoluteAdmin vs. method: :delete

Hey folks, I recently stumbled upon an issue, which caused my destroy links to malfunction. It’s bundled to using AbsoluteAdmin (http://admindesigns.com/demos/absolute/1.1/index.html). I’ve separated everything in my project into two folders – admin and front (for admin part I’m using AbsoluteAdmin and for the front part another theme). This is my loading order for admin.js (assets/javascripts/admin) :

I’ve spent a lot of time figuring out how to make all of those JS from AbsoluteAdmin work, thus, I think, this exact order is important. However, admin/main (which is located at vendor/javascripts/admin/main.js) apparently breaks UJS. After a bit of detective work there was only one candidate for this behavior – the function ‘runHeader();’

As you can see, I commented it already out (line 22 in the snippet and line 720 in the actual file) and now everything works as expected!

Eve-trader.net – the new source for EVE Online productioneers

Greetings, capsuleers!

Few days ago I launched my long time dreamed project – eve-trader.net (http://eve-trader.net). This services is intended to be a lightweight alternative to updating your excel sheets daily with current prices (most likely you will get them from eve-central.com). Via the eve-central.com API I fetch the prices on requested blueprints, calculate for you the cheapest material prices and suggest where you can sell the end product most expensive.

Settings and assumptions as of today:

  • Areas considered for calculation are all solar systems within 5 jumps around the five main trade hubs (which currently are – Jita, Amarr, Rens, Dodixie, Hek) and which are high sec
  • All skills are lvl 5 (which you probably should have if you considering make money with industry)
  • No fees and taxes are calculated (if they are hindering you to make profit you are producing the wrong thing)

The service is in it’s early stage, so be prepared to encounter some changes in near future. What is planned:

  • Having at least a few options available in an “expert” menu
  • News section
  • Implement user accounts where user can save their blueprints, thus, having a faster access to their favourite blueprints
  • Having a history saved for each blueprint.
  • A suggestions feature, where users can suggest new things and other users can vote on them.
  • Making market predictions based on Monte-Carlo-Simulation or Expected Shortfall methods.

Properly create and restore your development postgreSQL on production

So maybe you are like me, who is parsing a lot of static data into a development database, make an app around this data and then you don’t want to have an empty database on production, but instead you want to have a full copy of your development database.

After spending a few hours trying to make it work, there is one solution, that yielded exactly 0 errors (yay!)

On your local machine (in the shell, wherever you currently are) :

Then put it in some safe place on your remote machine:

Make a backup of your production database for safety sake (on your production server, of course)

If there is no production database yet on the server, proceed with creating it, elsewise you might need (if the app has users) to cut the current sessions, so check these out:

http://stackoverflow.com/questions/12924466/capistrano-with-postgresql-error-database-is-being-accessed-by-other-users

or

http://stackoverflow.com/questions/1237725/copying-postgresql-database-to-another-server?rq=1

Ok, now we have no database on production machine at all. Let’s create new production database:

Make sure to populate the password with the same password, as set up in database.yml for production user.

That’s it! No need to change the owner. Now let’s restore the backup file:

As of now I have no issues regarding the one error above.