Laravel 5: eloquent-sluggable resluggify relationship data - laravel-5.1

I am a newbie to Laravel and have been developing an app. I am using Laravel 5 and to get pretty URL's i am using eloquent-sluggable.
I have 2 tables, Users and Artists and their respective models. I have relationship in Artist table. In the Artists model i have the below code.
class Artist extends Model implements SluggableInterface
{
use SluggableTrait;
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'artists';
/**
* #var array
*/
protected $sluggable = [
'build_from' => 'users.name',
'save_to' => 'slug',
];
public function user()
{
return $this->belongsTo('App\User');
}
I am trying to use tinker to update the existing data in database to slug. I have created a new field in artists table called slug. When i run the below command:
$artists = \App\Artist::all()
foreach ($artists as $artist) { $artist->name->resluggify()->save(); }
i get below error:
[Symfony\Component\Debug\Exception\FatalThrowableError]
Fatal error: Call to a member function resluggify() on string
How can i update the existing data in the database?

I've just had a look at the documentation for cviebrock/eloquent-sluggable as I'm assuming this is the package you're using.
name in this case is just a string so you wouldn't be able to call any methods from it which is what you're code is trying to do.
Looking at it, the method resluggify() it is just a helper function for
sluggify(true) - true is just telling it to sluggify the model even if the model has already been "slugged"
So the following should work:
$artist->resluggify()->save()
Hope this helps!

I was able to resolve the issue. It was my mistake, i had to update the model to implement SluggableInterface and then use the Trait.
use SluggableTrait;
This resolved the issue and i was able to resluggify.

Related

What is best way to update domain class object with large number of variables

Suppose I have Employee domain class, I want to create object of domain class from params map coming from UI side.
I can create object in two ways as follows
Normal way
Employee employee = new Employee(name: params.name, rollNo:
params.rollNo)
and so on. If domain class has 20 variables, then we need to write all variables in above constructor.
Following is best way to create object
Employee employee = new Employee(params)
Above constructor will populate object with matching params. Right.
Now my question comes here.
If suppose I have existing domain class object fetched from DB, Now I want to update this object from params map coming from UI.
What is best way to do this (like we do in above second option).
I think it is best to use command objects and bind it to the Employee.
here is sample pseudo code:
class EmployeeMgmtController {
def editEmp(EmployeeCmd cmd){
Employee editEmp = Employee.get(1)
editEmp.properties = cmd
editEmp.save()
}
}
class EmployeeCmd{
String id
static constraints = {
id blank:false,nullable:false
}
}
or,
you if your on controller, and still want to use params (and exclude any fields that you don't want to bind):
bindData(editEmp, params, [exclude:['firstName', 'lastName']])
If you want to achieve that in a service class, make your service implement grails.web.databinding.DataBinder then use the bindData method as demonstrated below.
import grails.web.databinding.DataBinder
class MyAwesomeService implements DataBinder {
/**
* Updates the given instance of a domain class to have attribute values specified
* in "newData" map.
*/
MyDomain updateMyDomainAttributes(MyDomain myDomianInstance, Map newData) {
bindData(myDomianInstance, newData)
myDomianInstance.save(flush: true)
}
}

How to properly use Grails Command Objects

I've been struggling for a while reading and trying to understand command objects, but I've yet to understand how to use them in my particular scenario.
Here's what I have:
class Beneficary {
String name
//more attributes
static hasMany = [dependents = Dependent]
}
class Dependent {
DegreeKinship degreeKinship //enum
//several atrributes
static belongsTo = [beneficiary: Beneficiary]
}
I've read in several articles, including SO answers, that one should be using Command Objects for this if one wishes but I'm failing to understand just how.
I've wrote this:
class DependentCommand {
List<Dependent> dependents = ListUtils.lazyList([], {new Dependent()} as Factory)
}
but I'm not sure how to use it in my Beneficiary class.
Also, I wish to have it all under a single view (beneficiary/create)
Any help would be greatly appreciated.
I don't think you should use them in the Beneficary class, use them in BeneficaryController.
Command objects give you a standardized way of encapsulating, converting and validating request parameters. As such the main use for them is in a controller, not a domain class which can already do most of a command object's functions natively.
You could rewrite your command like this if you wanted to accept a request containing parameters along the lines of dependents=1&dependents=2:
class DependentCommand {
List<Dependent> dependents
}

Laravel 4: how to inject another class in a eloquent model

I'm trying to use the built-in laravel's Ioc container to inject a PageManager class inside a Page model and I'm a little lost.
What I'm trying to achieve is something like that:
class Pages extends Eloquent {
public function __construct(PagesManagerInterface $manager, array $attributes = array())
{
parent::__construct($attributes);
$this->manager = new $manager;
}
public function saveToDisk()
{
$this->manager->writeToFile();
}
But I obtain this error:
ErrorException: Argument 1 passed to Pages::__construct() must be an instance of PagesManagerInterface, none given.
I tried to add this in app/start/global.php:
App::bind('Pages',function(){
return new Pages(new PagesManager);
});
But is seems ignored by the framework, and also i don't know how to insert the $attribute array into this declaration.
I'm a little lost so any help is appreciated!
It's not a good idea to overload a model's constructor because new instances can be spawned behind the scenes through various methods, like Model::find().
When that happens, the dependencies you're asking for in your custom constructor aren't being passed in because the Model class isn't aware of them. So, you get that error message.
See the find() method here: http://laravel.com/api/source-class-Illuminate.Database.Eloquent.Model.html#380-397
See this post by Jason Lewis: http://forums.laravel.io/viewtopic.php?pid=47124#p47124
I think that what you need is:
App::bind('PagesManagerInterface',function(){
return new Pages(new PagesManager);
});
This tells Laravel to inject a new Page object everytime it needs an instance of your PagesManagerInterface wich wasn't passed while creating the model.
In Laravel you can use the IoC Container:
public function saveToDisk(){
$managerObject = app()->make('path\to\class\PagesManagerInterface');
$managerObject->writeToFile();
}

Referring to Related Record ID In Controller On Save()

I'm still new to Grails and GORM and I got stumped on this and wasn't able to figure out what I am doing wrong. The intent is to automatically relate the record to the logged in user through the Shiro plugin for Grails.
Class User { static hasMany = [stuff: Stuff] }
Class Stuff { static belongsTo = [user:User] }
Class StuffController {
def create = {
params.put('user', User.createCriteria().get{eq('username',SecurityUtils.subject.principal)}.id)
def stuffInstance = new Stuff(params)
stuffInstance.save()
}
}
I saw in the generate-views version of the create scaffold that the relevant field was referred to as name="user.id", but neither it nor variants (such as user_id) seems to work. The query to the Users domain returns the record id necessary, and params.put in this context seems to correctly append the params object with the new value when I render to a test page (so I'm guessing it's not immutable), but this is what I get from the save():
Property [user] of class [class org.stuffing.Stuff] cannot be null
I've even tried flipping it around and going the other way, with the same result:
User.createCriteria().get{eq('username',SecurityUtils.subject.principal)}
.addToStuff(new Stuff(params))`
.save()
Anyone able to enlighten me on what I'm missing here?
Thanks!
EDIT:
Apparently I was being braindead; I was overriding the "create" method, but the default action is "save" in the _form.gsp template, so it wasn't executing that branch.
On the plus side, I did learn about dynamic finders via Burt below, so it wasn't a total wash.
Thanks for your time, guys!
Your code can be a lot cleaner - there's no reason to use createCriteria here. If you're searching by username, use a dynamic finder:
def stuffInstance = new Stuff(params)
def user = User.findByUsername(SecurityUtils.subject.principal)
stuffInstance.user = user
if (!stuffInstance.save()) {
// inspect stuffInstance.errors
}

Loading DropDownList from model using Helper method

I have a bunch of commonly used Lists whcih need to populate dropdownlists. Instead of defining ViewModels with Lists here is what I am doing.
#Html.DropDownListFor(model => project.TypeID, new SelectList(#PSS.Helpers.ProjectTypes.ProjectTypesList(),"id","name"))
where the Helper class is defined as follows
namespace PSS.Helpers
{
public class ProjectTypes
{
public static List<ProjectType> ProjectTypesList()
{
MyContext db = new MyContext();
return db.ProjectTypes.ToList<ProjectType>();
}
}
}
Is there anything wrong with doing this? am I breaking any rules?
With this code you are likely to hit your database more times than you would want to. Because every time you hit this helper you are creating a new Entity Framework context and hitting the database to get your list of ProjectTypes. To me, that is bad.

Resources