A model fields and B model fields in same form
Ex:
public static function tableName()
{
return 'a';
}
public function rules()
{
return [
[['id','b_id'], 'id'],
];
}
public function beforeSave($insert)
{
//I want to save b model here
}
I cant access B model attributes in beforeSave()
Related
I have a logger user I want to show the articles, categories, for this user only.
Database schema:
Users: category: article:
id id id
name name title
users_id categories_id
User Model
class User extends Model
public function Category
{
return $this->hasMany(Category::class,'users_id');
}
category model (works)
class Category extends Model
{
public function article
{
return $this->hasMany(Article::class );
}
public function users
{
return $this->belongsTo(User::class, 'users_id');
}
article model (works)
class Article extends Model
{
public function category()
{
return $this->belongsTo(Category::class,'categories_id');
}
Controller category
class CategoryController extends Controller
{
public function index()
{
$categories = Category::all();
return view('category. view', compact('categories'));
}
class Article Controller extends Controller
{
public function index()
{
$articles = Article::all();
return view(' article . index', compact('articles'));}
In your controller you can use the following code:
public function getArticles(){
$user = auth()->user();
$articles = $user->articles;
return view('articlesView',array('articles' => $articles));
}
public function getCategories(){
$user = auth()->user();
$articles = $user->categories;
return view('categoryView',array('articles' => $articles));
}
In order for these functions to work you need to add these methods to your User model:
public function categories(){
return $this->hasMany('App\Category');
}
public function articles(){
return $this->hasMany('App\Articles');
}
public class EmployeeDetails {
private String name;
private double monthlySalary;
private int age;
/**
* #return the name
*/
public String getName() {
return name;
}
/**
* #param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* #return the monthlySalary
*/
public double getMonthlySalary() {
return monthlySalary;
}
/**
* #param monthlySalary the monthlySalary to set
*/
public void setMonthlySalary(double monthlySalary) {
this.monthlySalary = monthlySalary;
}
/**
* #return the age
*/
public int getAge() {
return age;
}
/**
* #param age the age to set
*/
public void setAge(int age) {
this.age = age;
}
}
How to pass the list of EmployeeDetails.class to the JUnit parameterized class.
Please help me on writing the Parameters method
#Parameters
public static Collection employeeList()
{
List<EmployeeDetails> employees = new ArrayList<EmployeeDetails>;
return employees;
}
// This throws error like "employeeList must return a Collection of arrays."
EmployeeDetails class above is for an example. I need to use it for a similar class where i will send the list of the class objects.
Your #Parameters method must return a collection of object arrays. So assuming your test case constructor just expects one EmployeeDetails object, do this:
#Parameters
public static Collection<Object[]> employeeList() {
List<EmployeeDetails> employees = new ArrayList<>();
// fill this list
Collection<Object[]> result = new ArrayList<>();
for (EmployeeDetails e : employees) {
result.add(new Object[] { e });
}
return result;
}
If you can use static constructors, you can be a lot terser in your setup
#Parameterized.Parameters
public static Collection<Object[]> params() {
return Arrays.asList(new Object[][] {
{ 0, "a" },
{ 1, "b" },
{ 3, "c" },
});
}
Collection is a generic type you must specify the type of the returned Collection<E> where E is the type, here it must be EmployeeDetails
your code must look like this:
public static Collection<EmployeeDetails> employeeList()
{
List<EmployeeDetails> employees = new ArrayList<EmployeeDetails>();
return employees;
}
or simply
public static Collection<?> employeeList()
{
List<EmployeeDetails> employees = new ArrayList<EmployeeDetails>();
return employees;
}
I have been searching the forums and the JSON.NET website on this issue and from what I can see I'm correctly following the guidelines but it is not working correctly.
I'm trying to deserialize object from derived classes.
Serializing works fine, but when deserializing it tries to deserialize in to the wrong type.
I'm trying to do this with Windows Phone 8 and JSON.NET 4.5.11
I have the following classes which I am serializing:
public class MyClass : ModelBase
{
public string Title { get; set; }
[JsonProperty(TypeNameHandling = TypeNameHandling.All)]
public MyAction Action {get; set; }
}
public abstract class MyAction : ModelBase
{
[JsonIgnore()]
public abstract ActionType ActionType { get; }
public abstract void Execute();
}
public class SettingsAction : MyAction
{
public override ActionType ActionType
{
get { return ActionType.Settings; }
}
public SettingsType SettingsType {get; set; }
public override void Execute()
{
}
}
public class NoneAction : MyAction
{
public override ActionType ActionType
{
get { return ActionType.None; }
}
public override void Execute()
{
return;
}
}
I serialize it like this:
MyClass obj = new MyClass
{
Action = new SettingsAction()
};
string json = JsonConvert.SerializeObject(
obj,
Formatting.Indented,
new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.All });
using (StreamWriter writer = new StreamWriter(stream))
{
writer.Write(json);
}
And it gives me the following JSON:
{
"$type": "Model.MyClass, Model",
"Title": null,
"Action": {
"$type": "Model.SettingsAction, Model",
"SettingsType": 0
}
}
As far as I can see, this is correct, I told it to include the type information and it's correctly included.
The I deserialize it like this:
using (StreamReader r = new StreamReader(stream))
{
string json = r.ReadToEnd();
MyClass obj = JsonConvert.DeserializeObject<MyClass>(json);
}
And I get the following error:
JsonSerializationException: Error setting value to 'SettingsType' on 'Model.NoneAction'
So, although the type is contained in the JSON, on serializing it's ignoring it and of course deserializing it into a different type fails.
Does anyone have an idea why it's not taking the information into account and deserialize to the correct type?
I have found the culprit:
In one of my properties I was doing this:
public MyAction Action
{
get
{
if (_Action == null) {
Action = new NoneAction();
}
return _Action;
}
set
{
if (value != _Action)
{
_Action = value;
NotifyPropertyChanged("Action");
}
}
}
The problem is in the getter, where I create a NoneAction if the obejct is null.
Apparently Json.NET calls into the getter at some point between creating the MyClass object and setting the values of the MyAction object. When it sees that the Action-property is not null, it tries to assign the values instead of overwrite the whole object.
I have some JSON where one of the keys has one of three values: an int, a string, or a json object. Using the snippet below I can map this field when it is an int or a string but fail when it's a json object. Where am I going wrong? What should I be doing?
The JSON value key looks like:
"value": 51,
or
"value": 51,
or (and this is where I am having trouble)
"value": {"lat": 53.990614999999998, "lng": -1.5391117000000301, "addr": "Harrogate, North Yorkshire, UK"}
public class Test {
public Test() {
}
public static class Value {
public int slidervalue;
public String voicevalue;
public GeoValue geovalue; // problem
public Value(int value) {
this.slidervalue = value
}
public Value(String value) {
this.voicevalue = value;
}
public Value(JSONObject value) {
JSONObject foo = value; // this is never reached
this.geovalue = value; // and how would this work so as map value to a GeoValue?
}
private static class GeoValue {
private double _lat;
private double _lng;
private String _addr;
public float getLat() {
return (float)_lat;
}
public void setLat(float lat) {
_lat = (double)lat;
}
public float getLng() { return (float)_lng;}
public void setLng(float lng) { _lng = (double)lng; }
public String getAddr() { return _addr;}
public void setAddr(String addr) { _addr = addr; }
}
} // end of Value class
public Value getValue() { return _value;}
public void setValue(Value value) {
_value = value;
}
} //end of Test class
and this is being used like this:
ObjectMapper mapper = new ObjectMapper();
instance = mInstances.getJSONObject(i).toString();
Test testinstance = mapper.readValue(instance, Test.class);
public class Test {
public Test() {
}
public static class Value {
public int slidervalue;
public String voicevalue;
public GeoValue geovalue; // problem
public Value(int value) {
this.slidervalue = value
}
public Value(String value) {
this.voicevalue = value;
}
public Value(JSONObject value) {
JSONObject foo = value; // this is never reached
this.geovalue = value; // and how would this work so as map value to a GeoValue?
}
private static class GeoValue {
private double _lat;
private double _lng;
private String _addr;
public float getLat() {
return (float)_lat;
}
public void setLat(float lat) {
_lat = (double)lat;
}
public float getLng() { return (float)_lng;}
public void setLng(float lng) { _lng = (double)lng; }
public String getAddr() { return _addr;}
public void setAddr(String addr) { _addr = addr; }
}
} // end of Value class
public Value getValue() { return _value;}
public void setValue(Value value) {
_value = value;
}
} //end of Test class
and this is being used like this:
ObjectMapper mapper = new ObjectMapper();
instance = mInstances.getJSONObject(i).toString();
Test testinstance = mapper.readValue(instance, Test.class);
This fails with a JSONMappingException: No suitable contructor found for type ... 'value'
Thanks. Alex
What might work is that you mark the constructor that takes JSONObject with #JsonCreator, but do NOT add #JsonProperty for the single parameter. In that case, incoming JSON is bound to type of that parameter (in this case JSONObject, but you could use Map as well), and passed to constructor.
Overloading still works because of special handling for single-string/int/long-argument constructor.
I am not sure if that is the cleanest solution; it might be cleanest to just implement custom deserializer. But it should work.
If your code is what you want, your json should be like this:
{"value":{"slidervalue":1,"voicevalue":"aa","geovalue":{"lat":53.990615,"lng":-1.53911170000003,"addr":"Harrogate, North Yorkshire, UK"}}}
Iam using .NET 3.5. I have asp.net mvc app. There is base controller:
public abstract class BackendController<TModel> : BaseController where TModel : class
{
// skipped ...
public ActionResult BatchDelete(int[] ids)
{
var entities = repository.GetList().Where(item => ids.Contains(item.ID));
repository.delete(entities)
}
public ActionResult BatchHide(int[] ids)
{
var entities = repository.GetList().Where(item => ids.Contains(item.ID));
repository.BatchUpdate(
entities.Where(item => item.IsHidden == false),
c => new TModel { IsHidden = true }
);
}
}
It is won’t compile, because of item.ID and item.IsHidden - but in runtime this is valid type with certain properties. How to make this compile?
Well, you could use an interface to describe the common properties, and add a constraint to TModel:
public interface IModel
{
int ID { get; }
bool IsHidden { get; set; }
}
...
public abstract class BackendController<TModel> : BaseController
where TModel : IModel, new()