multi.js is a user-friendly replacement for select boxes with the multiple attribute. It is mobile-friendly, easy to use, and provides search functionality. multi.js is also easy to customize and style with CSS.
by via jQuery-Plugins.net RSS Feed
"Mr Branding" is a blog based on RSS for everything related to website branding and website design, it collects its posts from many sites in order to facilitate the updating to the latest technology.
To suggest any source, please contact me: Taha.baba@consultant.com
multi.js is a user-friendly replacement for select boxes with the multiple attribute. It is mobile-friendly, easy to use, and provides search functionality. multi.js is also easy to customize and style with CSS.
For the last 6+ years, I've been managing the SitePoint Ruby channel. I was given the job by desperate, over-tasked folks trying to save a fledgling Ruby resource. I swallowed my Imposter Syndrome and took up the cause. It was an opportunity and decision that changed my life and career. The people at SitePoint are wonderfully intelligent and a joy with which to work. It is my sincerest belief that SitePoint wants to create content that makes people in software better.
With that being said, allow me to shift the focus of this post from "Hey, look what I did for 6 years!" to "Take opportunities that make you uncomfortable."
In 2011, I was a competent .NET resource. I had ridden the wave of ASP to ASP.NET and could ably write C#. However, I was frustrated. I found .NET and the software around it (like IIS) to be limiting and frustrating. At the time, there were projects like Castle Windsor that included excellent Dependency Injection Frameworks, a .NET port of Rails called Monorail, and some other frameworks that felt good to use. In fact, Monorail predated ASP.NET MVC and was, unfortunately, killed by Microsoft inventing it's own MVC platform instead of using the existing (and superior, IMO) framework. While ASP.NET MVC was a step in the right direction and a fine framework in its own right, I wanted to make Ruby my everyday.
Continue reading %Take Opportunities to Beat Imposter Syndrome%
I'll be honest, I don't do much testing. When it's really necessary and I'm working on big enterprise projects, I do, but in general, my personal projects are usually one-man-army proofs of concept, or fixes on already tested apps.
[author_more]
We've done our share of testing posts here at SitePoint, with more coming soon, but I wanted to show you a relatively new testing tool I found that caught my attention because of how unconventional it seemed.
Peridot is a BDD testing framework (so behavior driven testing) but for your units of code - not your business logic.
Wait, what?
Yes.
If you're familiar with Behat, you'll recognize this syntax (it should be fairly readable even if you're not familiar with it):
Feature: adding a todo
As a user
I want my todos to be persisted
So I don't have to retype them
Scenario: adding a todo
Given I am on "/"
When I fill in "todo" with "Get groceries"
And I press "add"
And I reload the page
Then I should see "Get groceries"
Scenario: adding a duplicate todo
Given I have a done todo "Pick up dinner"
And I am on "/"
When I fill in "todo" with "Pick up dinner"
And I press "add"
Then I should see "Todo already exists" after waiting
And I should see 1 "#todos li" elements
The individual phrases are defined in FeatureContext classes like so:
/**
* @Then I should see :arg1 after waiting
*/
public function iShouldSeeAfterWaiting($text)
{
$this->getSession()->wait(10000, "document.documentElement.innerHTML.indexOf('$text') > -1");
$this->assertPageContainsText($text);
}
/**
* @Given I have a todo :arg1
*/
public function iHaveATodo($todoText)
{
$collection = self::getTodoCollection();
$collection->insert(['label' => $todoText, 'done' => false]);
}
The framework recognizes them, substitutes the arguments for their values, and tests the conditions.
Continue reading %Testing Frenzy – Can We BDD Test the Units?%
Clearance is a simple authentication system with email and password built by the team at Thoughtbot. It has opinionated defaults but is intended to be easy to override. The system is actively maintained, and you can follow up on GitHub.
In this tutorial, you will see how to integrate Clearance into a Rails application. We will make use of a miniature application. Let's begin!
You'll start by generating your Rails application. For the purpose of this tutorial, I'll name mine tutsplus-clearance.
rails new tutsplus-clearance -T
That will do the magic.
You'll need bootstrap to make your application look good. Add the Bootstrap gem to your Gemfile.
#Gemfile ... gem 'bootstrap-sass'
Install the gem by running bundle install.
Now modify application.scss to look like this:
#app/assets/stylesheets/application.scss @import 'bootstrap-sprockets'; @import 'bootstrap';
Open your Gemfile to add the Clearance gem.
#Gemfile gem 'clearance'
Now install the gem.
bundle install
At this point, run the generator command to install clearance.
rails generate clearance:install
This will generate some outputs on your terminal, which look like what I have below:
create config/initializers/clearance.rb
insert app/controllers/application_controller.rb
create app/models/user.rb
create db/migrate/20161115101323_create_users.rb
*******************************************************************************
Next steps:
1. Configure the mailer to create full URLs in emails:
# config/environments/{development,test}.rb
config.action_mailer.default_url_options = { host: 'localhost:3000' }
In production it should be your app's domain name.
2. Display user session and flashes. For example, in your application layout:
<% if signed_in? %>
Signed in as: <%= current_user.email %>
<%= button_to 'Sign out', sign_out_path, method: :delete %>
<% else %>
<%= link_to 'Sign in', sign_in_path %>
<% end %>
<div id="flash">
<% flash.each do |key, value| %>
<div class="flash <%= key %>"><%= value %></div>
<% end %>
</div>
3. Migrate:
rake db:migrate
*******************************************************************************
When you ran the command, a couple of files were generated in your application. One such file is clearance.rb, which you can find in the config/initializers directory. A User model was also generated, and along with that you also have a migration file that looks like this:
class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.timestamps null: false
t.string :email, null: false
t.string :encrypted_password, limit: 128, null: false
t.string :confirmation_token, limit: 128
t.string :remember_token, limit: 128, null: false
end
add_index :users, :email
add_index :users, :remember_token
end
end
According to the output, the first thing you want to do is edit your config environment. To do that, navigate to config/environments/development.rb and add the line below, just above the end delimiter.
...
config.action_mailer.default_url_options = { host: 'localhost:3000' }
end
Next, navigate to config/initializers/clearance.rb to edit it, and when you're there, change the sender email address from the default to any of your choosing. This is what you will see when you open the file.
#config/initializers/clearance.rb Clearance.configure do |config| config.mailer_sender = "reply@example.com" end
You can override the default configuration by pasting in the following code snippet and configuring it to your requirements.
#config/initializers/clearance.rb
Clearance.configure do |config|
config.allow_sign_up = true
config.cookie_domain = ".example.com"
config.cookie_expiration = lambda { |cookies| 1.year.from_now.utc }
config.cookie_name = "remember_token"
config.cookie_path = "/"
config.routes = true
config.httponly = false
config.mailer_sender = "reply@example.com"
config.password_strategy = Clearance::PasswordStrategies::BCrypt
config.redirect_url = "/"
config.secure_cookie = false
config.sign_in_guards = []
config.user_model = User
end
Run the command to migrate your database.
rake db:migrate
Open your PagesController and add an index action.
#app/controllers/pages_controller.rb class PagesController < ApplicationController def index end end
Next, create a view for the index action you just created.
Add the code snippet below:
#app/views/pages/index.html.erb <h1>Tutsplus Clearance</h1> <p>Welcome to our Clearance Page.</p>
Edit your routes to:
#config/routes.rb Rails.application.routes.draw do root to: "pages#index" end
Create a partial named _navigation.html.erb inside the layouts directory. This will be used to handle everything that has to do with navigation on your application.
Paste the following code and save.
#app/views/layouts/_navigation.html.erb
<nav class="navbar navbar-inverse">
<div class="container">
<div class="navbar-header">
<%= link_to 'Tutsplus-Clearance', root_path, class: 'navbar-brand' %>
</div>
<div id="navbar">
<% if signed_in? %>
<ul class="nav navbar-nav">
<li><%= link_to 'Add Page', new_page_path %></li>
</ul>
<% end %>
<ul class="nav navbar-nav pull-right">
<% if signed_in? %>
<li><span><%= current_user.email %></span></li>
<li><%= link_to 'Sign out', sign_out_path, method: :delete %></li>
<% else %>
<li><%= link_to 'Sign in', sign_in_path %></li>
<% end %>
</ul>
</div>
</div>
</nav>
<div class="container">
<% flash.each do |key, value| %>
<div class="alert alert-<%= key %>">
<%= value %>
</div>
<% end %>
</div>
With Clearance, you can be able to create restricted access to specific pages of your choice in your application. Let's see how it is done.
Create a view for a new action in app/views/pages, the name of the file should be new.html.erb. Paste in the code below.
#app/views/pages/new.html.erb <h1>Restricted Page</h1> <p>This page is restricted to authenticated users, if you can see this it means you are a superstar!</p>
Now you need to add the line below to config/routes.rb.
#config/routes.rb ... resources :pages, only: :new ...
Finally, go to your PagesController make it like what I have below.
#apps/controllers/pages_controller.rb class PagesController < ApplicationController before_action :require_login, only: [:new] def index end def new end end
In the above code, we are making use of the Clearance helper, require_login, to restrict access to the new action. To see how it works, start up your rails server by running rails server from your terminal. Point your browser to http://locahost:3000/pages/new and it should redirect you to the sign in page.
Clearance also provides routing constraints that can be used to control access.
#config/routes.rb
Rails.application.routes.draw do
constraints Clearance::Constraints::SignedOut.new do
root to: 'pages#index'
end
constraints Clearance::Constraints::SignedIn.new do
root to: "pages#new', as: :signed_in_root
end
end
In the code above, a different route has been created for authenticated users.
A lot of things happen behind the scenes when you start using Clearance, things you cannot see. There might come a time when you want to customize things differently, depending on the specification of your application. Clearance allows you to override the default configuration it comes with.
To override (or generate) Clearance routes, run this command from your terminal.
rails generate clearance:routes
Your routes file should now look like this:
#config/routes.rb
Rails.application.routes.draw do
resources :passwords, controller: "clearance/passwords", only: [:create, :new]
resource :session, controller: "clearance/sessions", only: [:create]
resources :users, controller: "clearance/users", only: [:create] do
resource :password,
controller: "clearance/passwords",
only: [:create, :edit, :update]
end
get "/sign_in" => "clearance/sessions#new", as: "sign_in"
delete "/sign_out" => "clearance/sessions#destroy", as: "sign_out"
get "/sign_up" => "clearance/users#new", as: "sign_up"
root to: "pages#index"
resources :pages, only: :new
end
The command will also set the config.routes setting to false in your config/initializers/clearance.rb file. This means that the custom file which has just been generated will be used.
To generate views for modification, run:
rails generate clearance:views
Some of the files that will be generated include:
app/views/passwords/create.html.erb app/views/passwords/edit.html.erb app/views/passwords/new.html.erb app/views/sessions/_form.html.erb app/views/sessions/new.html.erb app/views/users/_form.html.erb app/views/users/new.html.erb config/locales/clearance.en.yml
You will see a prompt in your terminal asking to overwrite your app/views/layouts/application.html.erb file. Choose the option you want.
By default, Clearance uses your application's default layout. If you would like to change the layout that Clearance uses when rendering its views, simply specify the layout in an initializer.
Clearance::PasswordsController.layout "my_passwords_layout" Clearance::SessionsController.layout "my_sessions_layout" Clearance::UsersController.layout "my_admin_layout"
Clearance provides you with helper methods that can be used in your controllers, views, and helpers. These methods include signed_in?, signed_out?, and current_user. For example:
<% if signed_in? %> <%= current_user.email %> <%= button_to "Sign out", sign_out_path, method: :delete %> <% else %> <%= link_to "Sign in", sign_in_path %> <% end %>
Clearance has a lot to offer you when it comes to authentication, so be sure to try it out in your next project. You can learn more by checking out the GitHub page.
Statistical analysis of data helps us make sense of the information as a whole. This has applications in a lot of fields like biostatistics and business analytics.
Instead of going through individual data points, just one look at their collective mean value or variance can reveal trends and features that we might have missed by observing all the data in raw format. It also makes the comparison between two large data sets way easier and more meaningful.
Keeping these needs in mind, Python has provided us with the statistics module.
In this tutorial, you will learn about different ways of calculating averages and measuring the spread of a given set of data. Unless stated otherwise, all the functions in this module support int, float, decimal and fraction based data sets as input.
You can use the mean(data) function to calculate the mean of some given data. It is calculated by dividing the sum of all data points by the number of data points. If the data is empty, a StatisticsError will be raised. Here are a few examples:
import statistics
from fractions import Fraction as F
from decimal import Decimal as D
statistics.mean([11, 2, 13, 14, 44])
# returns 16.8
statistics.mean([F(8, 10), F(11, 20), F(2, 5), F(28, 5)])
# returns Fraction(147, 80)
statistics.mean([D("1.5"), D("5.75"), D("10.625"), D("2.375")])
# returns Decimal('5.0625')
You learned about a lot of functions to generate random numbers in our last tutorial. Let's use them now to generate our data and see if the final mean is equal to what we expect it to be.
import random import statistics data_points = [ random.randint(1, 100) for x in range(1,1001) ] statistics.mean(data_points) # returns 50.618 data_points = [ random.triangular(1, 100, 80) for x in range(1,1001) ] statistics.mean(data_points) # returns 59.93292281437689
With the randint() function, the mean is expected to be close to the mid-point of both extremes, and with the triangular distribution, it is supposed to be close to low + high + mode / 3. Therefore, the mean in the first and second case should be 50 and 60.33 respectively, which is close to what we actually got.
Mean is a good indicator of the average, but a few extreme values can result in an average that is far from the actual central location. In some cases it is more desirable to determine the most frequent data point in a data set. The mode() function will return the most common data point from discrete numerical as well as non-numerical data. This is the only statistical function that can be used with non-numeric data.
import random import statistics data_points = [ random.randint(1, 100) for x in range(1,1001) ] statistics.mode(data_points) # returns 94 data_points = [ random.randint(1, 100) for x in range(1,1001) ] statistics.mode(data_points) # returns 49 data_points = [ random.randint(1, 100) for x in range(1,1001) ] statistics.mode(data_points) # returns 32 mode(["cat", "dog", "dog", "cat", "monkey", "monkey", "dog"]) # returns 'dog'
The mode of randomly generated integers in a given range can be any of those numbers as the frequency of occurrence of each number is unpredictable. The three examples in the above code snippet prove that point. The last example shows us how we can calculate the mode of non-numeric data.
Relying on mode to calculate a central value can be a bit misleading. As we just saw in the previous section, it will always be the most popular data point, irrespective of all other values in the data set. Another way of determining a central location is by using the median() function. It will return the median value of given numeric data by calculating the mean of two middle points if necessary. If the number of data points is odd, it returns the middle point. If the number of data points is even, it returns the average of two median values.
The problem with the median() function is that the final value may not be an actual data point when the number of data points is even. In such cases, you can either use median_low() or median_high() to calculate the median. With an even number of data points, these functions will return the smaller and larger value of the two middle points respectively.
import random import statistics data_points = [ random.randint(1, 100) for x in range(1,50) ] statistics.median(data_points) # returns 53 data_points = [ random.randint(1, 100) for x in range(1,51) ] statistics.median(data_points) # returns 51.0 data_points = [ random.randint(1, 100) for x in range(1,51) ] statistics.median(data_points) # returns 49.0 data_points = [ random.randint(1, 100) for x in range(1,51) ] statistics.median_low(data_points) # returns 50 statistics.median_high(data_points) # returns 52 statistics.median(data_points) # returns 51.0
In the last case, the low and high median were 50 and 52. This means that there was no data point with value 51 in our data set, but the median() function still calculated the median to be 51.0.
Determining how much the data points deviate from the typical or average value of the data set is just as important as calculating the central or average value itself. The statistics module has four different functions to help us calculate this spread of data.
You can use the pvariance(data, mu=None) function to calculate the population variance of a given data set.
The second argument in this case is optional. The value of mu, when provided, should be equal to the mean of the given data. The mean is calculated automatically if the value is missing. This function is helpful when you want to calculate the variance of an entire population. If your data is only a sample of the population, you can use the variance(data, xBar=None) function to calculate the sample variance. Here, xBar is the mean of the given sample and is calculated automatically if not provided.
To calculate the population standard definition and sample standard deviation, you can use the pstdev(data, mu=None) and stdev(data, xBar=None) functions respectively.
import statistics from fractions import Fraction as F data = [1, 2, 3, 4, 5, 6, 7, 8, 9] statistics.pvariance(data) # returns 6.666666666666667 statistics.pstdev(data) # returns 2.581988897471611 statistics.variance(data) # returns 7.5 statistics.stdev(data) # returns 2.7386127875258306 more_data = [3, 4, 5, 5, 5, 5, 5, 6, 6] statistics.pvariance(more_data) # returns 0.7654320987654322 statistics.pstdev(more_data) # returns 0.8748897637790901 some_fractions = [F(5, 6), F(2, 3), F(11, 12)] statistics.variance(some_fractions) # returns Fraction(7, 432)
As evident from the above example, smaller variance implies that more data points are closer in value to the mean. You can also calculate the standard deviation of decimals and fractions.
In this last tutorial of the series, we learned about different functions available in the statistics module. You might have observed that the data given to the functions was sorted in most cases, but it doesn't have to be. I have used sorted lists in this tutorial because they make it easier to understand how the value returned by different functions is related to the input data.