Woman Attempts to ‘Mask-Shame’ Dude, Quickly Discovers Truth (Updated)

Woman Attempts to ‘Mask-Shame’ Dude, Quickly Discovers Truth (Updated)

https://ift.tt/38AFMXJ

UPDATE: Apparently I’m the one who got pranked. Here’s the original video that is "for entertainment purposes only." Personally, I still think it’s funny as hell.

Wearing a mask of yourself wearing a mask wrong is the trend America needs. It makes sense when you think of it. There are people in this country, silly, somewhat unhinged people, who think it’s their job to play mask police. If they see you maskless in public, you will be shamed! They feel it’s their "patriotic" duty. Plus, think of all the likes and retweets they can get on Twitter! Panic porn-addicted, overzealous mask advocates love the smell of each other’s flatulence.

When really, the truly patriotic thing to do is to f*** with these people. The last guy we saw do it, the other person at least had a sense of humor about it. This broad, not so much. The story starts with her smartphone out to document the alleged maskless person.

"I mean, I don’t understand why you would wear a mask like that."

You. People like YOU are why he would wear a mask like that. People who see someone not as masked up as the CDC says to be, and their first instinct ISN’T to mind their own beeswax. People’s whose first instinct is to lecture strangers in the store. People like YOU are the exact reason why someone would wear a mask like that.

Lady, take the L. You got caught in a prank. You’re not the only one with your smartphone out. In this instance, you were in fact the a-hole. Admit it. Laugh it off. Say, "You got me, dawg." Move on to the next aisle. Maybe you can spot two people only standing five feet and ten inches away from each other.


CAUGHT ON CAMERA! Entire Oakley School Board RESIGNS | Louder With Crowder

youtu.be

fun

via Louder With Crowder https://ift.tt/2pjixJJ

March 12, 2021 at 07:42AM

2019 Columbus Crime Data

2019 Columbus Crime Data

https://ift.tt/3leKZcP

I updated the Columbus Crime Statistics page with 2019 data, which is the latest year available. The data comes from what the city reported to the FBIā€™s Uniform Crime Reporting system.

2019 Violent Crime
-There were 5,350 incidents of violent crime in Columbus in 2019, down slightly from 2018ā€™s 5,365. The rate per 100K people was 595.4, down from 2018ā€™s 601.0.
-There is some discrepancy between the murders the city reported to the FBI- 81- and the total number of homicides it reported in its 2019 year-end report- 104. At 81 murders, it would be a rate of 9 per 100K, while 104 would be a rate of 11.6 per 100K. Even at 104, it would represent a drop from 2018ā€™s 109.
-There were 882 reported rapes, down from 2018ā€™s 894. There were 98.2 rapes per 100K, down from 2018ā€™s 99.9.
-Robberies continued their years-long decline, with 1,810 total and a rate of 201.4 per 100K. Robberies have declined 53% since 2007.
-There were 1,788 aggravated assaults at a rate of 199.0 per 100K. Assaults were higher than 2018ā€™s 1,615, but they are still down nearly 35% since they peaked in 1990.

Violent Crime Changes By Race 2010-2019
Other: -72.7%
Black: -34.6%
White: -21.3%
Unknown Race: -18.2%
Asian: +33.3%

Violent Crime Changes By Gender 2010-2019
Unknown Gender: -42.0%
Male: -35.2%
Female: +21.7%

Violent Crime Changes By Age Group 2010-2019
0 to 19: -41.2%
20 to 39: -33.9%
Unknown Age: -30.8%
40 to 59: +12.8%
60 and Over: +220.9%

Perhaps strangely, Asians, women and older people have seen their crime rates increase. In all 3 cases, the total crimes were relatively low in comparison to other groups, but the changes were significant enough to be noticeable.

2019 Property Crime
-There were 29,974 property crimes reported in 2019 for a rate of 3335.6 per 100K, down from 2018ā€™s 3596.3.
Property crimes peaked in 2001 with 62,151, but have fallen nearly every year since. The 2019 total was 51.8% lower than in 2001.
-Larceny thefts reached 20,606 for a rate of 2293.1 per 100K. This is both down from 2018ā€™s 2427.8 and 46.9% lower than their 2001 peak.
-Burglaries continued their dramatic fall in 2019. 5,809 were reported for a rate of 646.5 per 100K. This is down from 6,477 and 724.9 in 2018, and down nearly 62% just since 2010.
-There were 3,559 motor vehicle thefts for a rate of 396.1 per 100K in 2019, down from 3,962 and 443.7 in 2018. As with burglaries, motor vehicle thefts are down significantly in recent years, having fallen more than 58% just since 2004.

Property Crime Changes By Race 2010-2019
Other: -62.5%
White: -43.9%
Black: -27.7%
Unknown Race: +5.5%
Asian: +22.9%

Property Crime Changes By Gender 2010-2019
Male: -36.9%
Female: -23.3%
Unknown Gender: -0.9%

Property Crime Changes By Age Group 2010-2019
0 to 19: -48.7%
20 to 39: -33.1%
40 to 59: -25.5%
Unknown Age: +2.9%
60 and Over: +31.5%

Here are some additional crime-related links.
Columbus Police Department
National Crime Data Explorer

Like this:

Like Loading…

non critical

via All Columbus Data https://ift.tt/2ORoTMW

March 12, 2021 at 09:37AM

Report on COVID-related philanthropy credits MacKenzie Scott with powering 25% of U.S. giving

Report on COVID-related philanthropy credits MacKenzie Scott with powering 25% of U.S. giving

https://ift.tt/2PRK2vz

MacKenzie Scott. (Elena Seibert Photo)

A new report looking at the global philanthropic response to COVID-19 during 2020 credits MacKenzie Scott with singlehandedly powering 25% of the giving effort in the United States.

The report by the Center for Disaster Philanthropy and Candid looked at the sources of more than $20 billion awarded for pandemic-related causes, including corporations, foundations, public charities and high-net-worth individuals such as Scott.

By giving $4 billion of her Amazon-fueled wealth to 384 different nonprofits in December, Scott dramatically increased the proportion of giving by high-net-worth individuals. Of the $5.8 billion given by the group, Scott accounted for nearly three quarters of the amount.

The former wife of Amazon CEO Jeff Bezos took a more high-profile approach to her philanthropic giving in 2020.Ā She keyed on the destruction caused by the COVID-19 pandemic, calling it a ā€œwrecking ball in the lives of Americans already strugglingā€ and saying that ā€œeconomic losses and health outcomes alike have been worse for women, for people of color, and for people living in poverty.ā€

Scott, who is currently No. 21 on the Bloomberg Billionaires Index of wealthiest individuals, impacted several categories across the report with her giving, including:

  • BIPOC communities: Of U.S. COVID-19 philanthropy to specified recipients, 35% of dollars was explicitly designated for Black,Ā Indigenous and people of color (BIPOC) communities. High-net-worth donors in the data set designated a higher proportion of their funding for BIPOC communities (44 percent). This was almost entirely due to Scottā€™s grantmaking.
  • Health organizations: This group ranked second, accounting for 26% of dollars. Top health organizations included Gavi, the Vaccine Alliance, and the COVID-19 Therapeutics Accelerator. Easterseals (the national office combined with its affiliates) emerged in the top recipient list thanks to Scottā€™s $162 million award. The organization offers services and advocacy for people with disabilities.
  • Unrestricted or flexible support: This area dramatically increased in the second half of the year, with 39% of dollars and 21% of gifts to specified recipients described as unrestricted or flexible. Scottā€™s large, unrestricted grants accounted for the major shift.

The report lists Google as the top corporate donor, with 17 gifts totaling more than $1 billion.

The Bill and Melinda Gates Foundation was tops in funding by foundations, giving 398 gifts totaling $1.3 billion.

Scott made news earlier this week when it was revealed that she married Dan Jewett, a Seattle science teacher. Jewett signed on to The Giving Pledge, an initiative Scott previously committed to in which the ultra rich pledge to give their fortunes to charity.

In July 2020,Ā Scott named 116 non-profits that were receiving $1.67 billion of her wealth.

geeky

via GeekWire https://ift.tt/2pQ6rtD

March 10, 2021 at 02:58PM

T-Mobile Is Taking All of Your Sweet, Sweet Dataā€¦ Unless You Tell It to Stop

T-Mobile Is Taking All of Your Sweet, Sweet Dataā€¦ Unless You Tell It to Stop

https://ift.tt/3vcsiLk


Photo: John MacDougall (Getty Images)

Heads up, fellow T-Mobile customers: You might want to take a look at your mobile carrier’s privacy policy.

As first spotted by the Wall Street Journal, the company’s latest update to its privacy policy is set to automatically enroll paying phone subscribers into an ad-targeting program that will see their data shared with unnumbered advertisers starting next month. It’s also worth noting here that the privacy policy update also carries over for any Sprint customers who were gobbled by T-Mobile during the two company’s mega-merger last year.

T-Mobile’s latest Privacy Notice lays out some of the specifics: Starting April 26, the company writes, it will begin a “new program” that shares some personal data—like the apps you download or the sites you visit—with third-party advertisers. T-Mobile also adds that it won’t share your precise location data “unless you give [T-Mobile] your express permission,” and won’t share information in a way that can be directly tied back to your device. But like we’ve written before, just because a dataset is “anonymized” doesn’t mean that you can take the company anonymizing it (T-Mobile, in this case) at its word.

T-Mobile is hardly the only major telco to pull these kinds of ad-targeting shenanigans. Verizon, for example, has an entire subsidiary—Verizon Media—that compiles data from its customers (along with a few third parties) to make its own different audience categories for targeted ads. AT&T’s had its own adtech subsidiary, Xandr, on hand since 2018 for similar purposes: pooling similar buckets of subscriber data together, and then pawning off that data to advertisers that might be interested in reaching, say, new moms, vegetarians, or luxury shoppers on their specific networks.

The company, for its part, promised the Wall Street Journal that it was defaulting to this new setting because “many say they prefer more relevant ads,” which is one of the most oft-repeated arguments people in the ad industry like to throw around to justify their invasive practices. In fact, there’s another reason that T-Mobile might be incentivized to throw this update out right now.

G/O Media may get a commission

The ongoing updates to Apple’s iOS 14 and the upcoming updates to Google’s Chrome browser have left some advertiser’s core data-collection tactics—like mobile ID’s and third-party cookies—in the dust. Some major companies in the data-brokering space have begun pitching their own sorts of data-hoovering tech that can circumvent these new roadblocks, and T-Mobile’s new policy seems to be another spin on that, just coming from your phone service provider.

T-Mobile’s policy page, for its part, has a pretty comprehensive guide describing how to opt-out of this new program at the bottom of its new notice here, which is something you should go do right now.

geeky,Tech

via Gizmodo https://gizmodo.com

March 9, 2021 at 04:42PM

Livewire Demo: Full-Page Components in a Reusable Structure

Livewire Demo: Full-Page Components in a Reusable Structure

https://www.youtube.com/watch?v=xY0O2tSO8v0

Today I’m doing a code review, but it’s more like a showcase of a project that was architecturally fully built on Livewire. Let’s see the details and discuss this approach, what do you think?

programming

via Laravel News Links https://ift.tt/2dvygAJ

March 9, 2021 at 04:48PM

T-Mobile will tell advertisers how you use the web starting next month

T-Mobile will tell advertisers how you use the web starting next month

https://ift.tt/3qu9bsJ


The logo of Deutsche Telekom, owner of T-Mobile, seen over a booth at the Mobile World Congress expo hall.
Enlarge /

The logo of Deutsche Telekom, owner of T-Mobile, seen at Mobile World Congress in February 2019 in Barcelona, Spain.

Getty Images | NurPhoto

T-Mobile next month will start a new program that gives customers’ web browsing and device usage data to advertisers unless customers opt out of the data sharing.

“[S]tarting April 26, 2021, T‑Mobile will begin a new program that uses some data we have about you, including information we learn from your web and device usage data (like the apps installed on your device) and interactions with our products and services for our own and 3rd party advertising, unless you tell us not to,” T-Mobile said in a privacy notice. “When we share this information with third parties, it is not tied to your name or information that directly identifies you.”

For directions on how to opt out of the expanded data sharing, see the first section of the T-Mobile privacy notice.

T-Mobile, which completed its purchase of Sprint in April 2020, said that the new advertising “program changes the way Sprint offered choices for sharing in the past, as this data was previously used only if you indicated that it was OK with you first.”

It’s not clear exactly how big a change this is for non-Sprint customers of T-Mobile. An August 2020 version of the privacy policy said that T-Mobile collects “websites and URLs visited” but did not list smartphone customers’ web browsing data in the list of information shared with third parties. However, that August 2020 version said that T-Mobile sold “device identifiers and Internet and electronic network activity to facilitate certain advertising activities commonly deployed by online and technology companies.” A similar disclosure was in T-Mobile’s privacy policy before the Sprint acquisition as well.

T-Mobile says in another webpage describing its advertising and analytics program that it collects “addresses of websites visited; types of websites visited, like sports sites, music sites, etc.; applications, content, and features used—including how much time you spent using them, and information from servers that host these apps, content, and features.”

Advertising IDs used instead of customer names

In order to anonymize data before it’s sold to third parties, T-Mobile said that it ties the information “to your mobile advertising identifier or another unique identifier” instead of the customer’s name. But you’ll have to take T-Mobile’s word on just how anonymous the anonymized data actually is. “[P]rivacy groups say those IDs can be linked back to people by comparing different data sets,” The Wall Street Journal noted in an article on the T-Mobile changes today.

“It’s hard to say with a straight face, ‘We’re not going to share your name with it,'” Electronic Frontier Foundation lawyer Aaron Mackey told the Journal. “This type of data is very personal and revealing, and it’s trivial to link that de-identified info back to you.”

Before the merger with T-Mobile, “Sprint had previously shared similar data only from customers who opted into its third-party ad program,” the Journal wrote. ”We’ve heard many say they prefer more relevant ads so we’re defaulting to this [opt-out] setting,” a T-Mobile spokesperson told the Journal.

We asked T-Mobile several questions about the data-sharing changes and for details on how exactly it ensures that data can’t be linked to individual customers, and we’ll update this article if we get a response.

AT&T and Verizon data-sharing doesn’t go as far

The Journal article said that T-Mobile is being more aggressive in sharing individual customers’ Internet usage data with advertisers than AT&T and Verizon:

AT&T automatically enrolls wireless subscribers in a basic ad program that pools them into groups based on inferred interests, such as sports or buying a car. An enhanced version of the program shares more-detailed personal information with partners from customers who opt into it.

Verizon likewise pools subscriber data before sharing inferences about them with advertisers, with a more-detailed sharing program called Verizon Selects for users who enroll. Its separate Verizon Media division shares data gathered through its Yahoo and AOL brands.

AT&T says on this webpage that “We don’t share information about your individual web browsing or TV viewing” in its “relevant advertising” system, but offers an “enhanced relevant advertising” system that shares additional information only with customers’ “prior explicit consent.”

Verizon says on a relevant mobile advertising FAQ that “Information Verizon Wireless has about web activity from your mobile device is not used in the program.” The program does use “mobile and online web browsing information” collected by Verizon’s Yahoo and AOL subsidiaries, but this apparently wouldn’t cover browsing to non-Verizon websites. Customers can opt out of this targeted advertising program.

In 2016, Verizon agreed to pay a $1.35 million fine and give users more control over “supercookies” that identify customers in order to deliver targeted ads. Verizon’s previous use of the supercookies without properly notifying users violated an FCC rule that required Internet providers to disclose accurate information about network management practices to consumers.

Carriers sold location data without consent

T-Mobile and the other major carriers were previously caught selling their customers’ real-time location data to third-party data brokers without customer consent, violating a law banning sales of phone-location data. The Federal Communications Commission in February 2020 proposed a fine of $91 million for T-Mobile, the biggest for any of the major carriers, but T-Mobile said it would fight the penalty.

The Obama-era FCC tried to require home Internet and mobile broadband providers to get consumers’ opt-in consent before using, sharing, or selling Web browsing and app usage histories, but a Republican-controlled Congress and then-President Trump killed the rule in 2017 before it took effect.

geeky

via Ars Technica https://arstechnica.com

March 9, 2021 at 05:38PM

Gain Concealed Carry Confidenceā€¦From Home

Gain Concealed Carry Confidenceā€¦From Home

https://ift.tt/38mEaAQ

I remember the very first time I put a gun in a holster on my hip.Ā 

In short, I was terrified.Ā 

Concealed Carry Tugging at Shirt
Ohh the familiar ā€œtugging on the shirt because youā€™re terrified someone knows you have a gunā€ move.

It took me a couple of months after taking my concealed carry course before I felt truly ready to head out into public with my little Walther P22 strapped to my hip.

And Iā€™m not the only gun owner to feel the nerves when it comes time to leave the house with a gun.Ā 

Itā€™s a very common feeling to be unsure and even insecure with the thought of carrying when youā€™re new to the process.Ā 

Nervous
Yeah, weā€™ve been there.

But thatā€™s why you have us, friends.Ā 

Weā€™re here to pass on some tips to get you feeling confident and secure with your concealed carry setup.

Help

Weā€™ll talk about the importance of training (and where you can score some free courses), as well as how to do some things at home to help ease your fear.Ā 

So letā€™s get you ready to concealed carry!Ā 

If youā€™re looking for even more insight, check out Brownells Daily Defense video with Jeff Gonzales below

Tips for ConfidentĀ Concealed Carry

1. Get Training

Ok, so admittedly, this part might require you to leave home, but training is an essential part of the concealed carry equation.Ā 

If all you take is one state-approved CCW course, youā€™re likely not going to walk away with a ton of confidence.

Training with a RE Factor Kill Zone
Training is a great way to gain confidence.

Depending on the class, you might walk away with even more questions bouncing around your head.Ā 

So, if you can, sign up for another class geared towards concealed carry.

The more training you receive and the more hours you put in the classroom and on the range, the more confidence youā€™ll gain in your decision-making and skills.Ā 

8. Dry Fire Mag Mantis X App
Not all your training has to be outside the home. Dry fire tools can help work on fundamentals at home.

All of this translates into how you carry yourself in the real world with a gun strapped to you.Ā 

Bonus, you can totally explore concealed carry concepts and expert advice at home with programs like the USCCA.

Eric did a full review of the different tiers and which tier gets you the most FREE courses!

USCCA Proving Ground, Aftermath
USCCA Proving Ground ā€” an awesome resource!

2. Check Your Guns + Gear

Next, youā€™ll want to take stock of the guns and gear you have at your disposal.Ā 

Your carry setup can make or break your mindset, especially if youā€™re feeling iffy about everything. So, evaluate your CCW gun, holster, and belt.Ā 

Concealed Carry Glock 19, Belt, Holster
Concealed Carry Glock 19, Belt, Holster

First, determine if your gun really works for you.

The handgun you chose for home defense might do great in a bedside safeā€¦but may not perform so well in a holster.

Look at what guns you have, and donā€™t be afraid to step down to a smaller model if you need to.

S&W M&P Shield EZ shooting
Nothing wrong with a smaller gun.

(See our suggestions for great concealed carry models handguns.)

Thereā€™s nothing wrong with carrying a .380 ACP Sig Sauer P238, Ruger LCP, or a 9mm Smith & Wesson if thatā€™s all you feel you can reasonably conceal.Ā 

Concealed Carry Guns
Concealed Carry Guns (L to R: Gen 4. Glock G19, Smith & Wesson Shield, Sig Sauer P238)

Alternatively, if a Glock 19 feels the best ā€” go for it!Ā 

On a similar note, you want to make sure your holster and belt combo is set up for success. While most people do not want to invest $100 in a concealed carry belt, itā€™s worth shopping around a bit and finding a quality one.Ā 

By that, I mean a belt that is rigid enough to support the weight of a holster and gun.Ā 

Concealed Carry Holster Belt Gun
Volund Gearworks Atlas Belt, Dark Star Gear Orion Holster, Glock 19. All these work together to hold the gun in place.

Need recommendations? We have some in our Best Belts for Concealed Carry and the Range.Ā 

And finally, choose a quality holster that provides adequate protection for the gun while also offering access to the gun should you need it.Ā 

Holsters donā€™t have to be uncomfortable, but you should definitely prioritize safety and retention.Ā 

Concealed Carry Gun in Holster
Your holster should keep the gun nice and safe.

There are plenty of great options on the market!Ā 

But if you need holster inspiration, check out our list of the Best Concealed Carry Holsters. Ā 

3. Carry Around the House

Once you have your setup narrowed down, itā€™s time to practice!Ā 

The first time you suit up with a gun, it can feelā€¦well, weird. You might not feel immediately ready to head to Target, and thatā€™s ok.Ā 

Wearing your gun around the house is a great place to start to build that confidence, learn your gear, and familiarize yourself with concealed carry.Ā 

Concealed Carry Around House
Wearing your gun while you do housework will help you get accustomed to it. (Psst, thereā€™s a Glock 19 hiding under there.)

Heck, Iā€™ve been doing this for over 10 years, and I still like to try new outfits out at home before taking them into the wild.

Itā€™s a great testing ground to see what works and doesnā€™t.Ā 

So, pop that holster and unloaded gun on and take it for a test ride while you do laundry, cook dinner, or just hang.

Concealed Carry Around House
Sometimes me and the G19 like to just take a reading break.

Youā€™ll quickly start to identify the quirks of your system and how to address them.Ā 

4. Get Input from Friends

Once you feel pretty confident wearing your gun around the house, thereā€™s one more step to take before going into public. Get your friendsā€™ input.Ā 

Ask trusted friends and family to take a look at some outfits you intend to wear.Ā 

Concealed Carry Around House
Call some friends over to take a look at your outfit. Theyā€™ll be able to spot any issues.

Theyā€™re a great judge of a) your behavior and whether youā€™re concealing your intentions and b) the clothes you want to pair with your CCW rig.

While standing in front of a mirror can help you pinpoint some problem areas, you canā€™t see a full 360 view like your friends or family can. So, ask for help!Ā 

Concealed Carry Mirror
Yes, a mirror works too, but you might miss something on your own.

Conclusion

Concealed carry is practical, but itā€™s also an art form. Learning how to do it and do it well takes time and practice. (Not to mention lots of trial and error.)Ā 

Womens Brands Alexo Athletica Skirt
Get trained and get to know your gear.

Getting trained, carrying at home, evaluating your gear, and employing friendsā€™ help will help you work towards a more confident concealed carry experience.Ā 

Ready to learn more? Peep Brownells Daily Defense video with Jeff Gonzales below for more tips.

Do you have any at-home tips for better concealed carry? Let us know in the comments below. For even more concealed carry content, check out our Definitive Guide to Concealed Carry.Ā 

The post Gain Concealed Carry Confidenceā€¦From Home appeared first on Pew Pew Tactical.

guns

via Pew Pew Tactical https://ift.tt/2m7cc0U

March 8, 2021 at 06:43PM

Laravel Tutorial: Step by Step Guide to Building Your First Laravel Application

Laravel Tutorial: Step by Step Guide to Building Your First Laravel Application

https://ift.tt/2mS5E8j


Since its initial release in 2011, Laravel has experienced exponential growth. In 2015, it became the most starred PHP framework on GitHub and rose to the go-to framework for people all over the world.

Laravel focuses on the end-user first: which means it focus is on simplicity, clarity, and getting work done. People and companies are using it to build everything from simple hobby projects all the way to Fortune 500 companies.

My goal with this Laravel tutorial to create a guide for those just learning Laravel. This guide will take you from the very beginning of an idea into a real deployable application. If you’d prefer to read this as an ebook you can join our weekly Laravel Newsletter and get it for free.

This look at Laravel will not be exhaustive, but if you want a more exhaustive introduction I recommend the book Laravel: Up and Running. This tutorial does expect a few prerequisites and here is what you will need to follow along:

  • A local PHP environment (Valet, Homestead, Vagrant, MAMP, etc.).
  • A database (I’ll be using MySQL)
  • PHPUnit installed.
  • Node JS installed.

Note: For the local PHP development I Recommend Mac OSX and Valet because it automatically sets everything up. If you are on Windows, consider Homestead or some flavor of a virtual machine. Another option is a community-provided Windows port of Valet.

I am attempting to go through the process of creating a new application just as I would in a real-world environment. In fact, the code and idea are from a project I built.

Planning

Every project has to start somewhere; either a project assignment at work or just an idea in your head. No matter where it originates, thoroughly planning out all the features before you start coding is paramount in completing a project.

How you plan is dependent on how your mind works. As a visual person, I like to plan on paper, drawing out the way I picture the screens looking and then working backward into how I would code it. Others prefer to write a project plan in a text file, wiki, or some mind mapping tool. It doesn’t matter how you plan, just that you do it.

For this guide, we are going to be building a link directory. Here is a list of fundamental goals for this links app:

  1. Display a simple list of links.
  2. Create a form where people can submit new links.
  3. Validate the form.
  4. Insert the data into the database.

Let’s get started!

The First Steps

With a simple plan of attack outlined, it’s time to get a brand new empty project up and running. I like to put all my projects in a ~/Sites directory, and these instructions will use that location. I’ve already “parked” this directory in Valet, so any folders will automatically be mapped to “foldername.test” in the browser.

Open your terminal application and switch into this directory.

mkdir ~/Sites
cd ~/Sites

Laravel provides a convenient installer. If you’re planning on writing Laravel apps, follow the installation documentation for details on setting up the installer.

Whether you set up the installer or want to use composer, run one of the following to create a new Laravel project for the links application:

# Via the installer
laravel new links

# Via composer
composer create-project --prefer-dist laravel/laravel links "7.*"

This will create a new directory at ~/Sites/links and install a new Laravel project.

Visiting links.test in the browser now shows the default Laravel welcome page:

Database Setup

When you create a new Laravel project, the installation process automatically creates a .env file (copied from the .env.example file) for configuration and credentials. Depending on your setup, you’ll need to modify the following block of settings to match your database configuration:

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=

You may want to create a new database for this project:

# Connect via the mysql CLI
mysql -u root -p
mysql> create database links_development;
mysql> exit

# Or use the -e flag to run the create command
mysql -u root -e'create database links_development'

You would then want to adjust the database configuration in .env:

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=links_development
DB_USERNAME=root
DB_PASSWORD=

The best way to test your database connection is running the migrate artisan command:

php artisan migrate

If everything went according to plan, you should see something like the following after running the migrate command:

Authentication Scaffolding

Laravel has a separate first-party package for generating common scaffolding that makes setting up authentication a breeze. To use it, we need to install the UI composer package:

composer install laravel/ui

The UI package provides a few commands for setting up scaffolding for tools like React, Vue, and Bootstrap. We’ll create simple auth scaffolding for this project, but feel free to follow the frontend setup documentation.

Run the following to generate routes, controllers, views, and other files necessary for auth:

php artisan ui bootstrap --auth

Last, we need to compile our CSS UI with the following:

npm install

# Build dev assets
npm run dev

# Or use a watcher to automatically update changes
npm run watch

The watch command will listen for files changes to JS and CSS files, and automatically update them. You probably want to have npm run watch running in a separate tab while developing.

Even though this tutorial will not dive into authentication by running this command, it will modify our views and routes. So by doing it early, we don’t have to worry about it messing with any of our code.

With the basics set up and working, it’s time to start doing some coding.

Building a List of Links

If you start thinking about a finished project, it’s easy to get overwhelmed. The best way to fight this is to break the project down into small tasks. So, let’s start by showing a list of links.

Even though showing a list of links sounds like a small task it still requires a database, a database table, data in the table, a database query, and a view file.

Creating a migration will be the first step, and the Laravel Artisan command line tool can help us build that.

php artisan make:migration create_links_table --create=links

Now, open the file this command created. It will be located at database/migrations/_create_links_table.php. You’ll notice a few other migrations in this folder as well, which the framework provides.

Inside the “up()” method, add the following schema:

Schema::create('links', function (Blueprint $table) {
      $table->increments('id');
      $table->string('title');
      $table->string('url')->unique();
      $table->text('description');
      $table->timestamps();
});

Save the file and run the migration:

php artisan migrate

While you are working with test data, you can quickly apply the schema:

php artisan migrate:fresh

Next, we need some data and a model to work with our database table. Laravel provides two features to help with this, the first is a database seeder, which populates the database with data, and second, the model factory files that allow us to generate fake model data that we can use to fill our development database and tests:

php artisan make:model --factory Link

The make:model command creates an app/Link.php model file. Laravel models provide a powerful database API called Eloquent, which you can explore in great detail in the Eloquent documentation.

The --factory flag will generate a new factory file in the database/factories path for generating app data. In our case, a new LinkFactory file will include an empty factory definition for our Link model.

Open the LinkFactory.php file and fill in the following:

<?php

/** @var \Illuminate\Database\Eloquent\Factory $factory */

use App\Link;
use Faker\Generator as Faker;

$factory->define(Link::class, function (Faker $faker) {
    return [
        'title' => substr($faker->sentence(2), 0, -1),
        'url' => $faker->url,
        'description' => $faker->paragraph,
    ];
});

We use the $faker->sentence() method to generate a title, and substr to remove the period at the end of the sentence.

Next, create the link seeder, so we can easily add demo data to the table:

php artisan make:seeder LinksTableSeeder

The make:seeder command generates a new database class to seed our links table with data.

Open the database/seeds/LinksTableSeeder.php file and add the following:

public function run()
{
    factory(App\Link::class, 5)->create();
}

In order to “activate” the LinksTableSeeder, we need to call it from the main database/seeds/DatabaseSeeder.php run method:

public function run()
{
    $this->call(LinksTableSeeder::class);
}

You can now run the migrations and seeds to add data to the table automatically. Using the migrate:fresh command, we can get a clean schema that applies all migrations and then seeds the database:

$ php artisan migrate:fresh --seed
Dropped all tables successfully.
Migration table created successfully.
Migrating: 2014_10_12_000000_create_users_table
Migrated:  2014_10_12_000000_create_users_table
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated:  2014_10_12_100000_create_password_resets_table
Migrating: 2017_11_03_023418_create_links_table
Migrated:  2017_11_03_023418_create_links_table
Seeding: LinksTableSeeder

Using the tinker shell you can start playing around with the model data:

$ php artisan tinker
>>> \App\Link::first();
=> App\Link {#3060
     id: 1,
     title: "Rerum doloremque",
     url: "http://russel.info/suscipit-et-iste-debitis-beatae-repudiandae-eveniet.html",
     description: "Dolorem voluptas voluptatum voluptatem consequuntur amet dolore odit. Asperiores ullam alias vel soluta ut in. Facere quia et sit laudantium culpa ea possimus.",
     created_at: "2020-04-05 00:44:33",
     updated_at: "2020-04-05 00:44:33",
   }
>>>

We have the data place and a model to interact with the database! Let’s start building the UI to add new links to the application.

Routing and Views

To build out a view showing the list of links, we need to update the main project route and also define a new route that will display our submission form. We can add new routes to our application in the routes/web.php file.

In the web routes file you should see the default route below:

Route::get('/', function () {
    return view('welcome');
});

To create a new route, we can either use a route closure or a dedicated controller class. In this tutorial, we will use closures for our submission and index routes.

First, let’s update the home route by getting a collection of links from the database and passing them to the view:

Route::get('/', function () {
    $links = \App\Link::all();

    return view('welcome', ['links' => $links]);
});

The second argument can be an associative array of data, and the key ends up being the variable name in the template file.

You can also use a fluent API to define variables if you prefer:

// with()
return view('welcome')->with('links', $links);

// dynamic method to name the variable
return view('welcome')->withLinks($links);

Next, edit the welcome.blade.php file and add a simple foreach to show all the links:

@foreach ($links as $link)
    <a href=""></a>
@endforeach

Here’s what the welcome.blade.php HTML should look like:

<body>
    <div class="flex-center position-ref full-height">
        @if (Route::has('login'))
            <div class="top-right links">
                @auth
                    <a href="">Home</a>
                @else
                    <a href="">Login</a>
                    <a href="">Register</a>
                @endauth
            </div>
        @endif

        <div class="content">
            <div class="title m-b-md">
                Laravel
            </div>

            <div class="links">
                @foreach ($links as $link)
                    <a href=""></a>
                @endforeach
            </div>
        </div>
    </div>
</body>

If you refresh your browser, you should now see the list of all the links added. With that all set, let’s move to submitting links.

Displaying the Link Submission Form

We are almost done creating our first application in Laravel!

We will round out this Laravel tutorial with the ability for others to submit links into the app, which requires three fields: title, URL, and a description.

I am a visual person, and before planning out features requiring HTML, I like to draw them out so I can get an idea of what I’m building in my head. Here is a simple drawing of this form:

Since we’ve added all the core structure, model factory, migration, and model, in the last section, we can reap the benefits by reusing all those for this section.

First, create a new route in the routes/web.php file:

Route::get('/submit', function () {
    return view('submit');
});

Next, we need to create the submit.blade.php template at resources/views/submit.blade.php with the following boilerplate bootstrap markup:

@extends('layouts.app')
@section('content')
    <div class="container">
        <div class="row">
            <h1>Submit a link</h1>
        </div>
        <div class="row">
            <form action="/submit" method="post">
                @csrf
                @if ($errors->any())
                    <div class="alert alert-danger" role="alert">
                        Please fix the following errors
                    </div>
                @endif
                <div class="form-group">
                    <label for="title">Title</label>
                    <input type="text" class="form-control @error('title') is-invalid @enderror" id="title" name="title" placeholder="Title" value="">
                    @error('title')
                        <div class="invalid-feedback"></div>
                    @enderror
                </div>
                <div class="form-group">
                    <label for="url">Url</label>
                    <input type="text" class="form-control @error('url') is-invalid @enderror" id="url" name="url" placeholder="URL" value="">
                    @error('url')
                        <div class="invalid-feedback"></div>
                    @enderror
                </div>
                <div class="form-group">
                    <label for="description">Description</label>
                    <textarea class="form-control @error('description') is-invalid @enderror" id="description" name="description" placeholder="description"></textarea>
                    @error('description')
                        <div class="invalid-feedback"></div>
                    @enderror
                </div>
                <button type="submit" class="btn btn-primary">Submit</button>
            </form>
        </div>
    </div>
@endsection

There’s quite a bit going on in this form, so let’s go over the major points that might be confusing when you are new to Laravel.

Near the top of the form, we have a blade conditional that checks to see if there are any validation errors. When errors exist, the bootstrap alert message will be shown, prompting the user to fix the invalid form fields:

@if ($errors->any())
    <div class="alert alert-danger" role="alert">
        Please fix the following errors
    </div>
@endif

Each individual form field checks for validation errors and displays an error message and outputs a has-error class:

<div class="form-group">
    <label for="title">Title</label>
    <input type="text" class="form-control @error('title') is-invalid @enderror" id="title" name="title" placeholder="Title" value="">
    @error('title')
        <div class="invalid-feedback"></div>
    @enderror
</div>

If the user submits invalid data, the route will store validation in the session and redirect the user back to the form. The function will populate the originally submitted data. If a user forgot to submit one of the fields, the other fields that have data would be populated after validation fails and errors are shown.

If a field has an error, the @error directive provides an error message variable you can use within the directive block:

@error('title')
    <div class="invalid-feedback"></div>
@enderror

Another way to check and dispay errors involves the $error variable provided to the view after a validation failure and redirect:

@if($errors->has('title'))
    <div class="invalid-feedback"></div>
@endif

The @error directive uses the same variable under the hood, feel free to use whichever method you prefer.

Submitting the Form

With the form in place, we are ready to handle sending and validating form data on the server. Back in the routes/web.php file, create another route for the POST request:

use Illuminate\Http\Request;

Route::post('/submit', function (Request $request) {
    $data = $request->validate([
        'title' => 'required|max:255',
        'url' => 'required|url|max:255',
        'description' => 'required|max:255',
    ]);

    $link = tap(new App\Link($data))->save();

    return redirect('/');
});

Note: make sure you add use Illuminate\Http\Request near the top of web.php.

This route is a little more complicated than the others.

First, we are injecting the Illuminate\Http\Request object, which holds the POST data and other data about the request.

Next, we use the request’s validate() method to validate the form data. The validate method was introduced in Laravel 5.5 and is a nice shortcut over other methods used for validation. As a bonus, the validated fields are returned to the $data variable, and we can use them to populate our model.

We require all three fields, and using the pipe character we can define multiple rules. All three rules can have a max of 255 characters, and the url field requires a valid URL.

If validation fails, an exception is thrown, and the route returns the user with the original input data and validation errors.

Next, we use the tap() helper function to create a new Link model instance and then save it. Using tap allows us to call save() and still return the model instance after the save.

Typically, you would have to do the following without tap, it just adds a little syntactic sugar:

$link = new \App\Link($data);
$link->save();

return $link;

If we want to populate a new model with data, we need to allow the fields to be “fillable” via mass assignment. The fillable property is designed to prevent fields from being mass-assigned except for the items you define in the array.

Think about this for a minute: we are taking user input from the request and mass assigning the values on the database model. Be aware of the dangers of user-submitted data and take care to guard against data you don’t intend the user to directly manipulate via a form.

In our case, we are validating each field so allowing them to be mass-assigned is safe. To allow our model to assign values to these fields, open the app/Link.php file and update it to look like the following:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Link extends Model
{
    protected $fillable = [
        'title',
        'url',
        'description'
    ];
}

If we wanted to avoid mass-assignment, this is how our code might look:

$data = $request->validate([
    'title' => 'required|max:255',
    'url' => 'required|url|max:255',
    'description' => 'required|max:255',
]);

$link = new \App\Link;
$link->title = $data['title'];
$link->url = $data['url'];
$link->description = $data['description'];

// Save the model
$link->save();

The last thing we do in our POST route redirects the user back to the home page after saving the link successfully.

At this point, our form should prevent submitting links with invalid fields:

If the form passes validation, the data should be saved in the database and the user redirect back to the homepage.

Testing the Form Submission

We have a basic working form, but we should make sure it continues to work by writing tests.

Laravel makes HTTP testing a breeze for performing integration tests against routes and middleware, so let’s write a few feature tests to verify our code works as expected.

Before we get started, we need to adjust a few things in our phpunit.xml file so that we can use an in-memory SQLite database. You will need to make sure that you have the proper PHP modules installed.

As of Laravel 7, the project’s phpunit.xml file configures an in-memory SQLite database. If you’re using an older version of Laravel, change the database connection by adding the following:

<php>
        <!-- ... -->
    <env name="DB_CONNECTION" value="sqlite"/>
    <env name="DB_DATABASE" value=":memory:"/>
        <!-- ... -->
</php>

Next, remove the placeholder test that ships with Laravel:

rm tests/Feature/ExampleTest.php

We are ready to start testing the /submit form through HTTP requests to make sure that the route validation, saving, and redirecting are working as expected.

First, let’s create a new feature test to test against our route:

php artisan make:test SubmitLinksTest

The command creates a new testing file with the proper dependencies, including a RefreshDatabase trait that we are going to use to verify that our links are being saved to the database when valid.

Open the new tests/Feature/SubmitLinksTest.php file and let’s define a few skeleton tests in the body of the class that we are going to flesh out:

/** @test */
function guest_can_submit_a_new_link() {}

/** @test */
function link_is_not_created_if_validation_fails() {}

/** @test */
function link_is_not_created_with_an_invalid_url() {}

/** @test */
function max_length_fails_when_too_long() {}

/** @test */
function max_length_succeeds_when_under_max() {}

These tests should give you a high-level overview of what we are going to test:

  1. Verify that valid links get saved in the database
  2. When validation fails, links are not in the database
  3. Invalid URLs are not allowed
  4. Validation should fail when the fields are longer than the max:255 validation rule
  5. Validation should succeed when the fields are long enough according to max:255.

We might be missing some things, but for your first Laravel application, this is a decent list that should illustrate some basic HTTP testing techniques in Laravel.

Saving a valid link

The first test we’ll write is the test that verifies that valid data gets stored in the database:

<?php

namespace Tests\Feature;

use Illuminate\Validation\ValidationException;
use Tests\TestCase;
use Illuminate\Foundation\Testing\RefreshDatabase;

class SubmitLinksTest extends TestCase
{
    use RefreshDatabase;

    /** @test */
    function guest_can_submit_a_new_link()
    {
        $response = $this->post('/submit', [
            'title' => 'Example Title',
            'url' => 'http://example.com',
            'description' => 'Example description.',
        ]);

        $this->assertDatabaseHas('links', [
            'title' => 'Example Title'
        ]);

        $response
            ->assertStatus(302)
            ->assertHeader('Location', url('/'));

        $this
            ->get('/')
            ->assertSee('Example Title');
    }
}

Take note of the RefreshDatabase trait which makes sure that each test has a new database to give each test a pristine database environment with all the migrations.

Our first test submits valid post data, which returns a response object that we can use to assert that our route responded as expected. We verify that the database contains a record with the title we just created.

Next, we verify that the response was a 302 status code with a Location header pointing to the homepage.

Last, we request the home page and verify that the link title is visible on the homepage.

Let’s run our first test to make sure things pass as expected. Laravel 7 adds a new artisan test command, or you can use phpunit:

php artisan test

# Or run phpunit directly
vendor/bin/phpunit

You should see that the test suite passes:

Testing Failed Validation

When a user generally submits bad data, we expect the validation to trigger an exception and we can use that to make sure our validation layer is working:

/** @test */
function link_is_not_created_if_validation_fails()
{
    $response = $this->post('/submit');

    $response->assertSessionHasErrors(['title', 'url', 'description']);
}

We use Laravel’s assertSessionHasErrors() to make sure that the session has validation errors for each of our required fields. Because we submitted empty data to the route, we expect the required rule will trigger for each field.

Let’s run the test suite to verify our work thus far:

$ php artisan test tests/Feature/SubmitLinksTest

   PASS  Tests\Feature\SubmitLinksTest
  ✓ guest can submit a new link
  ✓ link is not created if validation fails

  Tests:  2 passed
  Time:   0.32s

Testing URL Validation

We expect only valid URLs to pass validation so that our application doesn’t try to display invalid data.

/** @test */
function link_is_not_created_with_an_invalid_url()
{
    $this->withoutExceptionHandling();

    $cases = ['//invalid-url.com', '/invalid-url', 'foo.com'];

    foreach ($cases as $case) {
        try {
            $response = $this->post('/submit', [
                'title' => 'Example Title',
                'url' => $case,
                'description' => 'Example description',
            ]);
        } catch (ValidationException $e) {
            $this->assertEquals(
                'The url format is invalid.',
                $e->validator->errors()->first('url')
            );
            continue;
        }

        $this->fail("The URL $case passed validation when it should have failed.");
    }
}

Laravel has a withoutExceptionHandling() method which disables Laravel’s route exception handling code used to generate an HTTP response after an exception. We use this to our advantage so we can inspect the validation exception object and assert against the error messages.

We loop through various cases (add your own if you’d like to cover more scenarios) and catch instances of ValidationException. If the text makes it past the exception handling, we manually fail the test because we expect the route throws a ValidationExcepiton exception each time.

The catch block uses the validator object to check the url error and asserts that the actual error message matches the expected validation error message.

I like using the try/catch technique, followed by a $this->fail() as a safety harness instead of using exception annotations provided by PHPUnit. Be sure to return in the caught exception to avoid confusing test failures. I feel catching the exception allows the ability to do assertions that wouldn’t otherwise be possible and provides a more granular control that I like in most cases.

Testing Max Length Validation

We will test a few scenarios with the max:255 validations rules: when the field fails max-length validation with a length of 256 characters, and when the field is long enough to pass validation at 255 characters.

Although Laravel contains the max validation rule functionality, I like to test it to verify that my application applies the rules. If someone removes the max validation rule, then the tests will catch it.

I like to test the threshold of min and max validation rules as an extra caution to make sure my application respects the min and max boundaries I set.

First, let’s test the “max length” scenario:

/** @test */
function max_length_fails_when_too_long()
{
    $this->withoutExceptionHandling();

    $title = str_repeat('a', 256);
    $description = str_repeat('a', 256);
    $url = 'http://';
    $url .= str_repeat('a', 256 - strlen($url));

    try {
        $this->post('/submit', compact('title', 'url', 'description'));
    } catch(ValidationException $e) {
        $this->assertEquals(
            'The title may not be greater than 255 characters.',
            $e->validator->errors()->first('title')
        );

        $this->assertEquals(
            'The url may not be greater than 255 characters.',
            $e->validator->errors()->first('url')
        );

        $this->assertEquals(
            'The description may not be greater than 255 characters.',
            $e->validator->errors()->first('description')
        );

        return;
    }

    $this->fail('Max length should trigger a ValidationException');
}

Again, we disable exception handling and create data that is one character too long to pass validation.

We assert each field to make sure they all have a max length validation error message.

Last, we need to return in the caught exception and use the $this->fail() as a safety harness to fail the test.

Next, we test the “under the max” scenario:

/** @test */
function max_length_succeeds_when_under_max()
{
    $url = 'http://';
    $url .= str_repeat('a', 255 - strlen($url));

    $data = [
        'title' => str_repeat('a', 255),
        'url' => $url,
        'description' => str_repeat('a', 255),
    ];

    $this->post('/submit', $data);

    $this->assertDatabaseHas('links', $data);
}

We make the form data long enough to pass max:255 validation and assert that the data is in the database after submitting the data.

Run the test suite and make sure everything is passing:

$ php artisan test tests/Feature/SubmitLinksTest

   PASS  Tests\Feature\SubmitLinksTest
  ✓ guest can submit a new link
  ✓ link is not created if validation fails
  ✓ link is not created with an invalid url
  ✓ max length fails when too long
  ✓ max length succeeds when under max

  Tests:  5 passed
  Time:   0.58s

Conclusion

Congratulations on making it through the tutorial!

This guide was designed to get you started on building your app, and you can use this as a building block to gain the skills you need to develop your application. I know this covers a lot of features and can be overwhelming if you are not familiar with the framework.

I hope this introduction to Laravel shows you why so many people are excited about the framework.

Join the weekly newsletter and check out the Laravel tutorials section of the site to go deeper and learn even more about Laravel.

programming

via Laravel News https://ift.tt/14pzU0d

March 7, 2021 at 12:04PM

How LEGO Bricks Are Made

How LEGO Bricks Are Made

https://ift.tt/2OqCEqm

How LEGO Bricks Are Made

Link

LEGO bricks are the worldā€™s favorite construction toys. We know theyā€™re made out of plastic, but how do they make so many different colors and shapes? And how do they package just the right quantity of the right bricks? The LEGO Group takes us inside of their factories for an inside look at how a finished set comes together.

fun

via The Awesomer https://theawesomer.com

March 5, 2021 at 05:45PM