How to Search and Replace in an Entire Document using Vim's %s Command
:%s/search_pattern/replacement_text/g
:%s/search_pattern/replacement_text/g
The custom hook created uses Meteor's useTracker hook and the subscribe method to subscribe to the article publication, as well as the ArticlesCollection to find the article with the matching _id (which is the same as the slug in this case).
const useArticle = (slug: string): any => {
const [error, setError] = useState<Error | null>(null)
return useTracker(() => {
const sub = Meteor.subscribe('article', { _id: slug })
if (sub.ready()) {
const article = ArticlesCollection.findOne({ _id: slug })
if (article) {
return {
loading: false,
error: null,
article,
}
} else {
setError(new Error(`Article with slug "${slug}" not found`))
return {
loading: false,
error,
article: undefined,
}
}
} else {
return {
loading: true,
error: null,
article: undefined,
}
}
}, [slug, setError])
}
This hook can be used in a React component to display the article, its loading state and error:
const Article = ({ slug }: { slug: string }) => {
const { loading, error, article } = useArticle(slug)
if (loading) {
return <div>Loading...</div>
}
if (error) {
return <div>Error: {error.message}</div>
}
return (
<div>
<h1>{article.title}</h1>
<p>{article.body}</p>
</div>
)
}
Eager loading with subqueries allows you to load related models using a subquery instead of joining the tables, which can improve performance in certain situations. For example, if you have a User model and a Post model, you can count the number of posts created by each user in the last month using a subquery like this:
$users = User::withCount(['posts as post_count' => function ($query) {
$query->select(DB::raw('count(*)'))
->where('created_at', '>', now()->subMonth());
}])->get();
In Laravel, both request classes and policies can handle authorization.
Request classes have an authorize method that is called automatically by the framework before the request is handled. It is a convenient way to perform authorization checks on a specific request.
Policies provide a more flexible and reusable way to handle authorization across multiple request classes. They are classes that organize authorization logic around a particular model or resource. They allow you to define granular abilities for your application's users and groups.
When both the request's authorize method and a policy's __call method (or method with the same name as the action) return false for the same action, the framework will consider the user as unauthorized and will return a 403 Forbidden response.
In such scenarios, the priority is given to the authorize method of the request class. If it returns true, the framework will continue to process the request and will not check against any policy. However, if it returns false or throws an exception, Laravel will check the policy's method with the same name as the action, and if it returns false, the user will be considered unauthorized and a 403 Forbidden response will be returned.
In summary, both request classes and policies can handle authorization in Laravel, with priority given to the authorize method of request classes.
In order to use TouchID on MacBook Pro for Terminal sudo prompts, we need to enable Apple's Touch ID PAM module pam_tid.so (https://opensource.apple.com/source/pam_modules/pam_modules-173.1.1/modules/pam_tid/pam_tid.c.auto.html).
/etc/pam.d/sudo
and addauth sufficient pam_tid.so
Heads up, when you do a system update this change will be most probably overwritten. In order to make it persistent, you need to create a launchd daemon.
pam-tid.sh
in a shared pathvim /Users/Shared/pam-tid.sh
#!/bin/bash
if ! grep 'pam_tid.so' /etc/pam.d/sudo --silent; then
sed -i -e '1s;^;auth sufficient pam_tid.so\n;' /etc/pam.d/sudo
fi
com.graffino.pam.plist
file:vim /Users/Shared/com.graffino.pam.plist`
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.graffino.pam</string>
<key>KeepAlive</key>
<false/>
<key>LaunchOnlyOnce</key>
<true/>
<key>RunAtLoad</key>
<true/>
<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/pam-tid.sh</string>
</array>
</dict>
</plist>
We can use web workers to execute the computationally intensive mapping operation in a separate thread. This can be done by following these steps:
// worker.ts
// define the input and output types
type WorkerInput<T, U> = { data: T, mapFn: (x: T) => U };
type WorkerOutput<U> = { data: U[] };
// function for the actual work on the data
function doWork<T, U>(input: WorkerInput<T, U>): Promise<WorkerOutput<U>> {
// Apply the mapping function to the input data.
const mappedData = input.data.map(input.mapFn);
// Return the mapped data as a promise.
return Promise.resolve({ data: mappedData });
}
// main.ts
const worker = new Worker('worker.ts');
// Define the mapping function.
const mapFn = (x: number) => x * x;
// Send data and the mapping function to the worker for processing.
worker.postMessage({ data: [1, 2, 3], mapFn });
// Listen for the message with the result from the worker
worker.addEventListener('message', (event) => {
console.log(`Received message from worker: ${event.data}`)
});
function getDatesInRange($dates, $start, $end) {
$datesInRange = $dates->filter(function ($date) use ($start, $end) {
if ((int) $start->format('Y') === (int) $end->format('Y')) {
$start->year((int)$date->format('Y'));
$end-> year((int)$date->format('Y'));
} elseif ((int) $start->format('Y') < (int) $end->format('Y')) {
if ((int) $date->format('m') >= (int) $start->format('m')) {
$start->year((int) $date->format('Y'));
$end->year((int) $date->format('Y'))->addYears(1);
} else {
$end->year((int) $date->format('Y'));
$start->year((int) $date->format('Y'))->subYears(1);
}
}
return Carbon::parse($date)->isBetween($start, $end);
});
return $datesInRange;
}
...
$period = CarbonPeriod::create($startDate, $endDate);
foreach ($period as $date) {
$date->format('Y-m-d');
}
$dates = $period->toArray();
To optimize the performance of a map function in JavaScript, you can do a few things:
Use the forEach method instead of map if you are not creating a new array from the iteration. forEach is faster because it does not create a new array.
Use the map method on a smaller array if possible. For example, if you have a large array and you only need to map over a subset of it, create a new array with just the subset and use map on that.
If you are using map to transform each element of the array, use a specialized method for the transformation instead of using map. For example, if you are transforming each element to a string, use the toString method instead of using map.
If you are using map to filter an array, use the filter method instead. filter is optimized for filtering and will be faster than using map for that purpose.
Use a for loop instead of map if you need to perform complex operations on each element of the array. map is optimized for simple transformations, so a for loop will be faster for more complex operations.
The challenge I encountered was accessing the Meteor.user()
in React Router's route loader
property.
Alternatively, instead of querying the server, I'm picking up the user id from localStorage. The absence of it indicates the user is logged off or never logged in. Until Meteor kicks off, no sensitive data is displayed anyway.
...
{
path: '/',
element: <App />,
errorElement: <ErrorPage />,
loader: async () => window.localStorage.getItem('Meteor.userId'),
}
...
and in app.tsx
:
const userId: UserId | null = useLoaderData()
const navigate = useNavigate()
useEffect(() => {
if (userId === null) navigate('/login')
}, [userId])