setting relationships in RSpec - ruby-on-rails-3

I'm new to RSpec and I have the following code.
class User < ActiveRecord::Base
attr_accessible :email, :name, :admin, :active, :password, :password_confirmation
has_many :venues
has_many :events
...
end
class Venue < ActiveRecord::Base
attr_accessible :name, :url, :street, :city, :state, :description, :user_id
belongs_to :user
...
end
FactoryGirl.define do
factory :user do
sequence(:name) { |n| "Person #{n}"}
sequence(:email) { |n| "foo#{n}#example.com"}
password "secret"
password_confirmation "secret"
factory :admin do
admin true
end
factory :active_user do
active true
end
end
factory :venue do
sequence(:name) { |n| "Venue #{n}"}
sequence(:url) { |n| "mail#venue#{n}"}
sequence(:street) { |n| "#{n} Main St."}
city "Chicago"
state "IL"
end
end
In my test I want to create a venue object which has a user_id set to user.id but the following doesn't work:
describe "as active user" do
let(:active_user) { FactoryGirl.create(:active_user) }
let(:user_venue) { FactoryGirl.create(:venue, user: active_user) }
let(:other_venue) { FactoryGirl.create(:venue) }

Try to change your venue factory to
# rspec/factories/venue.rb
FactoryGirl.define do
factory :venue do
sequence(:name) { |n| "Venue #{n}"}
sequence(:url) { |n| "mail#venue#{n}"}
sequence(:street) { |n| "#{n} Main St."}
city "Chicago"
state "IL"
user
end
end
And use it in your spec this way
describe "as active user" do
let(:active_user) { FactoryGirl.create(:active_user) }
let(:user_venue) { FactoryGirl.create(:venue, user_id: active_user.id) }
...
end

Related

django rest framework serializer.save() inernal error

When I try to create a user I get 500 internal error when serializer.save() method is called. It worked fine yesterday and after a good sleep it stopped working.
class UserCreate(APIView):
parser_classes = (MultiPartParser,)
def post(self, request):
serializer = UserSerializer(data=request.data)
print(request.data)
if serializer.is_valid():
user = serializer.save()
if user:
return Response(serializer.data, status=status.HTTP_201_CREATED)
else:
return Response(serializer.errors, status=status.HTTP_304_NOT_MODIFIED)
class UserSerializer(serializers.ModelSerializer):
email = serializers.EmailField(
required=True, validators=[UniqueValidator(queryset=User.objects.all())]
)
username = serializers.CharField(
validators=[UniqueValidator(queryset=User.objects.all())]
)
password = serializers.CharField(min_length=8)
def create(self, validated_data):
user = User.objects.create_user(
validated_data["username"],
validated_data["password"],
validated_data["email"],
cellphone=validated_data["cellphone"],
sex=validated_data["sex"],
first_name=validated_data["first_name"],
last_name=validated_data["last_name"],
profile_image=validated_data["profile_image"],
)
return user
class Meta:
model = User
fields = (
"id",
"username",
"password",
"email",
"cellphone",
"sex",
"first_name",
"last_name",
"profile_image",
)

Silverstripe assumes SiteTree relation is to Parent?

My (partial) DataObject:
class InternalExternalLink extends DataObject {
private static $db = array(
'ExternalLink' => 'VarChar(256)',
'LinkLabel' => 'VarChar(256)',
"LinkType" => "Enum(array('Internal', 'External','Attachment'))"
);
private static $has_one = array(
'InternalLink' => 'SiteTree',
'Attachment' => 'File'
);
function getCMSFields() {
$fields = new FieldList(array(
$internal = DropdownField::create("InternalLinkID", "Choose a page", SiteTree::get()->map()->toArray())->setEmptyString("-- choose --"),
));
return $fields;
}
Add I add this to Page:
class Page extends SiteTree {
private static $has_many = array(
'Links' => 'InternalExternalLink'
);
function getCMSFields() {
$fields = parent::getCMSFields();
$gridField = new GridField('Links', 'Links', $this->Links(), GridFieldConfig_RecordEditor::create());
$fields->addFieldsToTab('Root.Main', $gridField);
return $fields;
}
The problem is when adding Links via the gridfield it automatically assumes that the Link.InternalLink is the parent page, rather than any page, and hides the page select drop down. E.g. if I am editing the about-us page then every Link dataobject I add via the gridfield automatically sets its InternalLink to the about-us page.
How do I change this assumption to allow me to select any page via the dropdown?
Try this:
1) Give the DataObject a "Parent" relation:
class InternalExternalLink extends DataObject {
private static $has_one = array(
'Parent' => 'DataObject',
'InternalLink' => 'SiteTree',
'Attachment' => 'File'
);
...
}
2) Specify "Parent" in the page's has_many:
class LinkTestPage extends SiteTree {
private static $has_many = array(
'Links' => 'InternalExternalLink.Parent'
);
...
}
The problem here is the relation on InternalExternalLink is to SiteTree whereas you're trying to define a relationship back to it on Page. As there's no has_one from InternalExternalLink to Page, and you're using a slightly older version of 3.1, the default has_one of Parent is looked for.
To solve this, you can either change the InternalLink relation to point to Page instead of SiteTree or use a DataExtension to add the has_many relation on to SiteTree.

yii cgridview relation multiple level

I have 4 tables of order payments user and profiles. Payments has a belongs_to relation with order. Order has a belongs_to relation with user, and user has_many profiles.
While displaying payments in cgridview I need to display the firstname and lastname of user stored in profile.
I tried using:
$data->order->user->profiles->firstname;
Also tried to add parameter firstname to the model class of Payment and tried to create the setter method as:
public function getFirstname(){
if ($this->_firstname=== null && $this->order !== null) {
$this->_firstname = $this->order->user->profiles->firstname;
}
return $this->_firstname ;
}
public function setFirstname($value){
$this->_firstname = $value ;
}
But I have not been able to get the desired result.
Edit: the search method has the following code:
public function search() {
$criteria = new CDbCriteria;
$criteria->with = array('order.user.profiles') ;
. . . .
$criteria->compare('firstname', $this->_firstname, true);
. . . .
return new CActiveDataProvider($this, array(
'criteria' => $criteria,
));
}
I would suggest using the "through" relation as it makes life easier. All you have to do is, goto your "payments" model and add the following relations,
public function relations()
{
return array(
'order' => array(self::BELONGS_TO, 'Orders', 'order_id'),
'user'=>array(
self::BELONGS_TO,'User',array('user_id'=>'id'),'through'=>'order'
),
'profiles'=>array(
self::HAS_MANY,'Profile',array('id'=>'user_id'),'through'=>'user'
),
);
}
and in the grid you can access the first_name by using,
$data->profiles[0]->firstname
try this in model:
public function getFirstname(){
return $this->order->user->profiles->firstname;
}
and in the grid:
$data->firstname;

How to map more than one tier of subclasses to nhibernate entity (with bycode)?

I am trying to setup some mappings and am getting this exception:
Cannot extend unmapped class: CommonEntity
[MappingException: Cannot extend unmapped class: CommonEntity]
NHibernate.Cfg.XmlHbmBinding.ClassBinder.GetSuperclass(String
extendsName) +217
NHibernate.Cfg.XmlHbmBinding.MappingRootBinder.AddEntitiesMappings(HbmMapping
mappingSchema, IDictionary`2 inheritedMetas) +352
NHibernate.Cfg.XmlHbmBinding.MappingRootBinder.Bind(HbmMapping
mappingSchema) +85
NHibernate.Cfg.Configuration.AddDeserializedMapping(HbmMapping
mappingDocument, String documentFileName) +156
I have 3 classes. Entity, CommonEntity and User. Theres no entity or commonentity table, only a User table. User inherits from CommonEntity and CommonEntity inherits from Entity. Entity and CommonEntity are abstract.
I have defined this mapping:
public class Mapping : ConventionModelMapper
{
public Mapping()
{
IsRootEntity((type, declared) =>
{
return typeof(Entity<Guid>) == type.BaseType;
});
IsEntity((x,y) => typeof(Entity<Guid>).IsAssignableFrom(x) && !x.IsAbstract && !x.IsInterface);
Class<Entity<Guid>>(x =>
{
x.Id(c => c.Id, m=>m.Generator(Generators.GuidComb));
x.Version(c=>c.Version, (vm) => { });
});
}
}
Which is used like this:
var types = typeof(Mapping).Assembly.GetExportedTypes().Where(t => typeof(Entity<Guid>).IsAssignableFrom(t));
var mapping = new Mapping().CompileMappingFor(types);
configuration.AddMapping(mapping);
Both User and CommonEntity are in the "types" array. I have tried adding a mapping for CommonEntity too but it made no difference.
Class<CommonEntity>(x =>
{
x.Property(c => c.DateCreated, m => m.Type<UtcDateTimeType>());
x.Property(c => c.DateModified, m => m.Type<UtcDateTimeType>());
});
Also tried calling Subclass instead of Class. If i inherit User directly from Entity everything works fine. Any help?
The problem appears to have been that CommonEntity was meeting the requirement for IsRootEntity. I modified it like so and things seem to be working now.
IsRootEntity((type, declared) =>
{
return !type.IsAbstract &&
new[] {typeof (Entity<Guid>), typeof (CommonEntity)}.Contains(type.BaseType);
});

Read-Only Joined Collection in NHibernate

Here is the basic situation. In our application, we have Roles and Permissions. There is a many-to-many relationship between roles and permission. The catch is, that a user can be assigned roles directly, or they can have a role that they have acquired by paying for a service. To make things more interesting, if the user cancels the paid service, or it expires, then they should no longer have that role. My issue is that I would like to have a (read-only) collection of the Effective Permissions on any given user, and I'd like to be able to query against it. Some mapping details:
public ApplicationPermissionMap()
{
Table("CLSYS_ApplicationPermissions");
Id(ap => ap.ID)
.Column("ApplicationPermissionID")
.GeneratedBy.Assigned();
//...
}
public ApplicationRoleMap()
{
Table("CLSYS_ApplicationRole");
Id(role => role.ID)
.Column("ApplicationRoleID");
HasManyToMany(r => r.Permissions)
.Table("CLSYS_ApplicationRolePermissions")
.ParentKeyColumn("ApplicationRoleID")
.ChildKeyColumn("PermissionID")
.Cascade.None();
//...
}
public PaidServiceMap()
{
Table("ECOM_PaidService");
Id(ps => ps.ID)
.Column("PaidServiceID");
Component(ps => ps.Status, statusMapping =>
{
statusMapping.Map(status => status.ID)
.Column("StatusID")
.Not.Nullable();
});
HasManyToMany(ps => ps.ApplicationRoles)
.Table("ECOM_PaidServiceRoles")
.ParentKeyColumn("PaidServiceID")
.ChildKeyColumn("RoleID")
.Cascade.None();
//....
}
public UserMap()
{
Table("CLSYS_User");
Id(user => user.ID)
.Column("UserID");
HasManyToMany(user => user.Roles)
.Table("CLSYS_User_ApplicationRoles")
.ParentKeyColumn("UserID")
.ChildKeyColumn("RoleID")
.Cascade.None();
//...
}
What I need is something like this (an addition to UserMap above)
public UserMap()
{
//...
HasMany(user => user.EffectivePermissions)
//Union ( user -> ApplicationRoles -> permissions)
//Union ( user -> PaidServices [with active status] -> permissions)
//Distinct
}
And I would like to be able to query on these permissions like so
_session.Linq<User>().Where(u => u.EffectivePermssions.Contains(somePermission) && user.SomeOtherCriteria == something);
I understand that I wouldn't be able to modify this collection directly, and that is perfectly acceptable. Can anyone help me out with this mapping?
As a short term solution, I have created a view that handles the union logic, and have the following mapping:
HasManyToMany(user => user.EffectivePermissions)
.Table("VW_CLSYS_User_EffectiveApplicationPermissions")
.ParentKeyColumn("UserID")
.ChildKeyColumn("ApplicationPermissionID")
.Inverse();
This is not ideal, as I'd prefer to have the logic in the mapping for the user. Any other suggestions are welcome.