Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: Allow Sushi to work even when there is no data available. #84

Merged
merged 5 commits into from
Apr 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,3 +143,28 @@ class Role extends Model
}
}
```
### Handling Empty Datasets
Sushi reads the first row in your dataset to work out the scheme of the SQLite table. If you are using `getRows()` and this returns an empty array (e.g an API returns nothing back) then Sushi would throw an error.

If you would like Sushi to work even if the dataset is empty, you can define your schema in the optional `protected $schema` array.

> Note: If you choose to use your own ->getRows() method, the rows will NOT be cached between requests.

```php
class Currency extends Model
{
use \Sushi\Sushi;

protected $schema = [
'id' => 'integer',
'name' => 'string',
'symbol' => 'string',
'precision' => 'float'
];

public function getRows()
{
return [];
}
}
```
23 changes: 23 additions & 0 deletions phpunit.xml.bak
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/8.5/phpunit.xsd"
bootstrap="vendor/autoload.php"
executionOrder="depends,defects"
forceCoversAnnotation="true"
colors="true"
beStrictAboutCoversAnnotation="true"
beStrictAboutOutputDuringTests="true"
beStrictAboutTodoAnnotatedTests="true"
verbose="true">
<testsuites>
<testsuite name="default">
<directory suffix="Test.php">tests</directory>
</testsuite>
</testsuites>

<filter>
<whitelist processUncoveredFilesFromWhitelist="true">
<directory suffix=".php">src</directory>
</whitelist>
</filter>
</phpunit>
42 changes: 37 additions & 5 deletions src/Sushi.php
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,23 @@ protected static function setSqliteConnection($database)
public function migrate()
{
$rows = $this->getRows();
$firstRow = $rows[0];
$tableName = $this->getTable();

if (count($rows)) {
$this->createTable($tableName, $rows[0]);
} else {
$this->createTableWithNoData($tableName);
}

foreach (array_chunk($rows, 100) ?? [] as $inserts) {
if (!empty($inserts)) {
static::insert($inserts);
}
}
}

public function createTable(string $tableName, $firstRow)
{
static::resolveConnection()->getSchemaBuilder()->create($tableName, function ($table) use ($firstRow) {
// Add the "id" column if it doesn't already exist in the rows.
if ($this->incrementing && ! array_key_exists($this->primaryKey, $firstRow)) {
Expand Down Expand Up @@ -126,12 +140,30 @@ public function migrate()
$table->timestamps();
}
});
}

foreach (array_chunk($rows, 100) ?? [] as $inserts) {
if (!empty($inserts)) {
static::insert($inserts);
public function createTableWithNoData(string $tableName)
{
static::resolveConnection()->getSchemaBuilder()->create($tableName, function ($table) {
$schema = $this->schema;

if ($this->incrementing && ! in_array($this->primaryKey, array_keys($schema))) {
$table->increments($this->primaryKey);
}
}

foreach ($schema as $name => $type) {
if ($name === $this->primaryKey && $type == 'integer') {
$table->increments($this->primaryKey);
continue;
}

$table->{$type}($name)->nullable();
}

if ($this->usesTimestamps() && (! in_array('updated_at', array_keys($schema)) || ! in_array('created_at', array_keys($schema)))) {
$table->timestamps();
}
});
}

public function usesTimestamps()
Expand Down
26 changes: 23 additions & 3 deletions tests/SushiTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public function setUp(): void
{
parent::setUp();

config(['sushi.cache-path' => $this->cachePath = __DIR__.'/cache']);
config(['sushi.cache-path' => $this->cachePath = __DIR__ . '/cache']);

if (! file_exists($this->cachePath)) {
mkdir($this->cachePath, 0777, true);
Expand Down Expand Up @@ -78,7 +78,7 @@ function models_using_the_get_rows_property_arent_cached()
/** @test */
function uses_in_memory_if_the_cache_directory_is_not_writeable_or_not_found()
{
config(['sushi.cache-path' => $path = __DIR__.'/non-existant-path']);
config(['sushi.cache-path' => $path = __DIR__ . '/non-existant-path']);

Foo::count();

Expand Down Expand Up @@ -116,6 +116,13 @@ function adds_primary_key_if_needed()
$this->assertEquals([5,6], ModelWithNonStandardKeys::orderBy('id')->pluck('id')->toArray());
$this->assertEquals(1, Foo::find(1)->getKey());
}


/** @test */
function it_returns_an_empty_collection()
{
$this->assertEquals(0, Blank::count());
}
}

class Foo extends Model
Expand Down Expand Up @@ -154,7 +161,8 @@ class ModelWithVaryingTypeColumns extends Model
{
use \Sushi\Sushi;

public function getRows() {
public function getRows()
{
return [[
'int' => 123,
'float' => 123.456,
Expand Down Expand Up @@ -219,3 +227,15 @@ class Baz extends Model
{
use \Sushi\Sushi;
}

class Blank extends Model
{
use \Sushi\Sushi;

protected $columns = [
'id' => 'integer',
'name' => 'string'
];

protected $rows = [];
}