I've got a many-to-many relationship in my Application between Users and Conversations
App.User = DS.Model.extend,
conversations: DS.hasMany('App.Conversation')
App.Conversation = DS.Model.extend
participants: DS.hasMany('App.User')
But every time i create and save a conversation, ember tries to save each participant including the ids of their related conversations. But i want the exact opposite of that, i want it to update just that one conversation and send the related participant_ids with it.
Is there a way to make that work?
What i tried so far:
specifying the inverse key on the user model (conversations: DS.hasMany('App.Conversation', inverse: 'participants'))
the workaround below.
.
App.RESTAdapter = DS.RESTAdapter.extend
serializer: DS.RESTSerializer.extend
addHasMany: (hash, record, key, relationship) ->
type = record.constructor
name = relationship.key
serializedHasMany = []
embeddedType = this.embeddedType(type, name)
return unless embeddedType is 'always'
record.get(name).forEach (record) ->
serializedHasMany.push record.get('id')
, #
hash[#singularize(key) + '_ids'] = serializedHasMany
App.RESTAdapter.map 'D4S.Conversation',
participants:
embedded: 'always'
After that it will save the conversation including the foreign keys but still tries to update the users, so i tried to save it with a custom request and just reset participant sates :/
App.Conversation._createWith = (participants) ->
conversation = #createRecord()
participants.forEach (p) ->
conversation.get('participants').addObject(p)
# conversation.save()
adapter = conversation.get('store._adapter')
adapter.ajax(adapter.buildURL('conversation'), 'POST',
data: { conversation: conversation.serialize() }
).then ->
conversation.setProperties(arguments[0].conversation)
conversation.get('stateManager').transitionTo('saved')
conversation.get('participants').forEach (user) ->
user.get('stateManager').transitionTo('saved')
conversation.trigger('didCommit')
conversation
Which finally worked \o/ But throw up the next error :(
Upon loading ember doesn't load the relationship, conversations participants property is always an empty DS.ManyArray
So is there a way to make that work?
Solution: Implement your own mapping key, don't use one thats already used.
This implementation solved all my problems:
serializer: DS.RESTSerializer.extend
###
Custom implementation to realize manySaving mapping
###
addHasMany: (hash, record, key, relationship) ->
#_super(hash, record, key, relationship)
type = record.constructor
name = relationship.key
serializedHasMany = []
manySaving = this.manySaving(type, name)
return unless manySaving
record.get(name).forEach (record) ->
serializedHasMany.push record.get('id')
, #
hash[key] = serializedHasMany
###
Check if manySaving option for a specific relationship is enabeld
#param {String} type The record type (usally a model class)
#param {String} name The attribute name of the relationship
#return {Boolean}
###
manySaving: (type, name) ->
this.mappingOption(type, name, 'manySaving')
D4S.RESTAdapter.map 'D4S.User',
conversations:
manySaving: false
D4S.RESTAdapter.map 'D4S.Conversation',
participants:
manySaving: true
key: 'participant_ids'
Related
I want regex search on mongodb with NodeJS.
First One is Users and Second one is categories. Here I have saved categories id in Users
collection. I want a search Query that filter my records.
Users collection
{_id:'mongo_id', name:"User First",cat_id:2}
{_id:'mongo_id', name:"User Second",cat_id:2}
{_id:'mongo_id', name:"User Third",cat_id:1}
{_id:'mongo_id', name:"User Fourth",,cat_id:4}
Categories
Suppose id is numeric. For demo purpose I have written numeric values.
{_id:'1', name:"Salesman",}
{_id:'2', name:"Carpanter"}
{_id:'3', name:"Plumber"}
{_id:'4', name:"Engineer"}
I have a text input if I will type Carpanter or Carpan(regex) then I want 2 records, or
When I type User Second or second I want 1 Record
var query = {
'name': {
$regex: req.body.name,
$options: 'i'
}
};
innerQuery = {
path: 'category',
select: 'name'
}
Users.find(query)
.populate(innerQuery)
.sort({
'createdDate': -1
})
Your user record looks like this:
{_id:'mongo_id': name:"User First",cat_id:2}
I'll assume the extra : is a typo.
Aside from that, you are attempting to query for title. There is no path title in that record, so you can't query for it.
You're also trying to populate the path category, but there is no field with that name in the user records. The only related field I see is cat_id.
If you want to, for example, query by name and populate the cat_id, you can do something like this:
var query = {
'name': {
$regex: req.body.title,
$options: 'i'
}
};
var innerQuery = {
path: 'cat_id',
model: 'Category',
select: 'name'
};
This is entirely dependent on whether you named your model Category, and also what your schemas actually look like.
(PS, you're also trying to sort by createdDate, but I don't see that field in any of your records, either).
How does one go about partial updates (i.e. via PATCH)? rake routes indicates that def update handles PUT and PATCH. This is how my Rails API is setup:
#user.first_name = user_params[:attributes][:'first-name']
#user.last_name = user_params[:attributes][:'last-name']
In user model. Both first_name and last_name have validates … presence: true. However, client, is trying to hit the endpoint with just attributes[first-name]. Note, attributes[last-name] is not being passed in the request. Rails thinks that #user.first_name has a value, but #user.last_name is nil. So a validation error is thrown
One way I thought of going about this was something like:
#user.first_name = user_params[:attributes][:'first-name'].present? ? user_params[:attributes][:'first-name'] : #user.first_name
#user.last_name = user_params[:attributes][:'last-name'].present? ? user_params[:attributes][:'last-name'] : #user.last_name
Is this a viable approach? Or is there something better I can consider?
EDIT. A more sophisticated problem is when I need to pre-calculate before actually saving the object. Take for example a product trying to update its price against a discount value, if present
def update
product = Product.find(params[:id])
product.amount_in_cents = product_params[:attributes][:'amount-in-cents']
product.discount_in_percentage = product_params[:attributes][:'discount-in-percentage'].present? ? product_params[:attributes][:'discount-in-percentage'].to_f : nil # Can be 0.10
if product.discount_in_percentage.present?
product.amount_in_cents = product.amount_in_cents + (product.amount_in_cents * product.discount_in_percentage)
else
product.amount_in_cents = product.amount_in_cents
end
if product.save
# ...
end
end
In Rails, we have a convention that the attributes in Model should be fetched to the Rails App like user[first_name] , user[last_name] and in controller we build a private method like users_params which will represent the data to be fed to the User model. like
# in controller
def update
user = User.find(params[:id])
user.update(users_params)
end
private
# This will prepare a whitelisted params data
def users_params
params.require(:user).permit(:first_name, :last_name, ...)
end
No need of this
#user.first_name = user_params[:attributes][:'first-name'].present? ? user_params[:attributes][:'first-name'] : #user.first_name
#user.last_name = user_params[:attributes][:'last-name'].present? ? user_params[:attributes][:'last-name'] : #user.last_name
In your case, you need to reformat the params keys to first_name instead of first-name and so forth. This will help you do your stuff with ease.
Tip: Try to keep it simpler as possible
I have a table order with such fields id, name, email, order_id etc.
I want create new table user and transfer name, email data from order table and create relation oneToMany (user -> order) and add new column to order table user_id which relate to user table
I wrote migration script for a new table
class UserMigration implements Migration, RenameExtensionAwareInterface
{
/**
* #param Schema $schema
* #param QueryBag $queries
* #return void
*/
public function up(Schema $schema, QueryBag $queries)
{
$table = $schema->createTable('user');
$table->addColumn('id', 'integer', ['autoincrement' => true]);
$table->addColumn('name', 'string', ['length' => 65]);
$table->addColumn('email', 'string', ['notnull' => false, 'length' => 129]);
$table->addColumn('createdAt', 'datetime');
$table->setPrimaryKey(['id']);
}
}
But I can’t find information how to correct get data fromn exits table and insert into new and in table order add FK(user_id).
I used this doc https://github.com/orocrm/platform/tree/master/src/Oro/Bundle/MigrationBundle
if both user and order are your own entities - you should check doctrine documentation about migrations and fixtures,
if you'd like to create relation from magento order, you should use extend extension in your migration, see examples in other orocrm bundle's migrations.
I'm building a simple Ember application using Ember v1.0.0 and Ember-Data v1.0.0-beta.3. I have a model called 'Categoria'
categoria.coffee:
App.Categoria = DS.Model.extend
nombre: DS.attr 'string'
simplified: DS.attr 'boolean'
candidatos: DS.hasMany 'candidato'
When I try to find a 'Categoria' by it's id, I always get error message:
Assertion failed: No model was found for 'categorium'
categoria_route.coffee:
App.CategoriaRoute = Em.Route.extend(
model: (params)->
#store.find('categoria', params.categoria_id)
)
App.CategoriaIndexRoute = Em.Route.extend(
model: ->
categoria = #modelFor('categoria')
categoria.reload() if categoria.get('simplified')
categoria
)
I've specified the inflections rules, due the spanish-named model.
store.coffee:
Ember.Inflector.inflector.irregular('categoria', 'categorias')
Ember.Inflector.inflector.rules.irregularInverse['categorias'] = 'categoria'
App.ApplicationAdapter = DS.ActiveModelAdapter()
App.ApplicationSerializer = DS.ActiveModelSerializer.extend()
I'm wondering if the find method of the Store uses a different set of inflections rules? or is there any other place where I should declare the inflection rules for this model?
It worths to mention that requests to the server for this model are made correctly (to the right URL) and they're responded well formed.
I've tried to use different syntax for the store.find method as mentioned in the Ember Guides#Method Find (http://emberjs.com/api/data/classes/DS.Store.html#method_find) but the error is the same.
The problem is when it tries to singularize the json response, it attempts to singularize categoria and it returns categorium, your pluralization was working fine.
var iff = Ember.Inflector.inflector;
iff.irregular('categoria', 'categorias');
// this adds a test for when it finds categoria and you are trying to singularize, return categoria
iff.singular(/categoria/, 'categoria');
http://emberjs.jsbin.com/ICeGuzuX/3/edit
I am working in a Symfony 1.4 project with Propel 1.4.2.
I have 2 related tables. workshop and trainers which is a many to many relation mapped by a join table (workshop_trainers) which contains the workshop_id and the trainer_id).
In my Workshop Form I have a select box for adding the trainers to the workshop. The problem is when the workshop is new (Create) I get an error:
Cannot add or update a child row: a foreign key constraint fails
This happens because, when saving the workshop_trainers relation the workshop_id field is null. Isn´t Propel intelligent enough to know that there is a relation between the tables and save the base object first? What I am doing wrong?
My trainer list widget.
$this->widgetSchema['workshop_trainer_list'] = new sfWidgetFormChoice(array(
'choices' => $trainers,
'multiple' => true,
));
Thanks for your help.
This is not fixing the problem but that's the easiest practical solution to this problem:
In the form, simply deactivate the workshop_trainer_list field if the object is a new one (doesn't have an ID yet).
Something like:
if ($this->getObject()->isNew())
{
$this->offsetUnset('workshop_trainer_list'); // not sure of that method name
}
A better solution is to update the doSave method to have the ID first, something like this:
protected function doSave($con = null)
{
$isNew = $this->getObject()->isNew();
if (null === $con)
{
$con = $this->getConnection();
}
// retrieve the value of workshop_trainer_list here and remove it from the form
$trainers = ...
$this->offsetUnset('workshop_trainer_list');
// save without it
parent::doSave($con);
// add it back
$this->getObject()->set...
// save
$this->getObject()->save($con);
}