Fast questions:
Is possible to build multiple level nested objects? How to do this?
#main_object = Object.new
#main_object.build_anotherobject
THe questions are: how to build more objects inside theese children objects? And is that a correct thing to do in Rails?
#main_object.another.others.build??
I don't know how to do that and if this is a good way to achieve multiple level nested objects.
Another question is about handling foreign keys in these nested objects. Some light how to get the correct FK?
I see that i would need to save the objects in a correct order because i need to validate the existence of a row in a parent table and then insert the valid FK inside a child with parent_id.
I could forget a big part of this problem and put many informations inside 1 table instead, but i would like to learn in a professional way, avoiding repeated informations in DB isn't a good point? For example, many people/user lives at same states, same cities, so i'm thinking that i shouldn't save the same strings over and over.
THanks for all attention!
You will need to assign it to a variable:
another_object = #main_object.build_anotherobject
And then:
another_object.even_more_objects.build
Repeat as you need to.
Related
Say we have an object A and we want to link it with a sortable list of Publications. But also, we have another object B which also has a sortable list of Publications. Publication objects may be shared between the lists.
Sorting order is defined in the backend and results in some integer property sort. Obviously, we cannot store this property as part of Publication object, because its’ sorting order is different in relation to different objects (A & B) and we’ll just needlessly update these objects every time we update lists, resulting in unwanted notifications.
I see a couple of ways to achieve this:
In SQL world, we can make many-to-many link via an intermediary table, where we can also store some properties, associated with a link, like sort. We can do something like this with Realm, but it’s a bit inconvenient and feels like API misuse.
We can make another List property with sorting order for the list stored in it. Though it’s even more inconvenient and strange.
Thanks in advance for clarification.
After some experiments, I concluded that this way feels as the most natural one, if you only want an ordered list of dependencies:
Make a List of ordered primary keys for the entity you want to "join".
Throw in some accessors to fetch necessary objects.
Still clumsy and you can't query dependencies.
There is something I don't really get with ruby-on-rails (I'm very new to it).
If my understanding is correct we use the model objects in the views.
The model object is the exact representation of the database. But in a lot of cases what we want to show in the view isn't the exact representation of the database.
Let's say we have an object line in the database:
line [line_id, quantity, category_id]
So if I want to show a list of lines there is no problem I can use the model object "line". But what if I want to show one line by category with a sum of the quantity for that category ?
Should I use the line object ? I feel bad about that because each line will not reflect a line in the database.
Should I create another kind of object ? Some sort of ViewModel that doesn't exist in the database but is usefull for rendering.
I'm not sure this is very clear... Thanks in advance for any help.
Always displaying data exactly as it is in the database happens only in tutorials :)
In real-world apps it is often necessary to transform data before presenting. This has many names: ViewModel (as you mentioned), Decorator, Presenter and others. So yes, make new objects for this, there's no reason not to.
If you display categories with a column in the view that shows the total quantity for each category, it would make sense to use the Category class in your application. This should be an ActiveRecord model.
On this model, you can define a method that reads the lines and sums the quantity. It could look like this:
def total_quantity
lines.map(&:quantity).sum
end
This method will read your lines (assuming you have set up a has_many :lines relationship in the Category class. Then it will read the quantity method on each lines and put the result in an array. Finally it will add the values together.
Note that this approach is a starting point and not very fast for larger sets of data. The approach can be improved through either lazy loading or specialized queries.
As your application grows in size, the number of methods such as the one above may grow in size to the point where the Category class becomes hard to understand. At this point, you may want to start looking for an intuitive ways to extract these methods into separate classes.
I'm doing a fairly complicated model on Ruby on Rails right now, and I was wondering what the correct "Rails" way of doing "custom types" for attributes was. For example, I have a table businesses which has a string attribute region. But region can only be one of a predefined list of possibilities (that could later be expanded). My question is: where do I define this Region type?
I know I could make a specific regions table (i.e. a Region model) which could house all the options, and then I could make an association between the models that have regions to that table. The problem is that I have many of these types on my model, so I would end up with more than half the tables in my database being "custom type tables" that only store the possible values for these types. Is that practical?
I also read that you could do this through validations (i.e. validate when saving a record, that the variables were within the possible values). This seems very impractical, since I want to make this model expandable, and form views would need to load the possible values of types into select boxes, etc. If I used this method, every time I needed to add a new possible value for a type, I'd have to change the validation and the views.
Is there a standard way of doing something like this? Something like defining types (maybe models without DB backing?) where I could list all the possible values easily?
Thank you for any help or suggestions on this. It's been bothering me for a long time while doing RoR apps, and I'm tired of hacking around it.
I guess there are many different ways to do it. Personally I would keep things very simple and DRY.
In an initializer, set arrays in the global scope:
REGIONS = ["region A", "region B", "region C"]
In the models, use validations as you wrote. Check that the value is in the REGIONS array.
In the views, use Rails helpers to populate selects, radios etc. from the REGIONS array. If you always have the same select, write your own helper region_select for instance.
I am trying to do the following in my iPad app. I have a structure that allows people to create grouped lists which we call "Templates". So The top level CoreOffer(has Title) which can have many groups(has grouptitle/displayorder) which can have many items(has ItemTitle, DisplayOrder). As shown below. This works great, I can create Templates perfectly.
Image link
http://img405.imageshack.us/img405/9145/screenshot20110610at132.png
But once Templates are created people than can use them to map against the Template which I will call an Evaluation. A Template can be used many times. The Evaluation will contain a date(system generated) and which items from this particular Template have been selected.
Example below, people will be able to check particular rows in the screen below, this is then an Evaluation.
Image link
http://img41.imageshack.us/img41/8049/screenshot20110610at133.png
I am struggling to figure out how to create and store this information in the core data model without duplicating the Template. (struggling coming from a SQL background!) In SQL this would involve something like an evaluation table recording each itemid and its selection status.
I expect its quite simple but I just cant get my head around it!
Thanks
The first thing you want to do is clean up the naming in your data model. Remember, you are dealing with unique objects here and not the names of tables, columns, rows, joins etc in SQL. So, you don't need to prefix everything with "Core" (unless you have multiple kinds of Offer, Group and Item entities.)
Names of entities start with uppercase letters, names of attributes and relationships with lower case. All entity names are singular because the modeling of the entity does not depend on how many instances of the entity there will be or what kind of relationships it will have. To-one relationship names should be singular and to-many plural. These conventions make the code easy to read and convey information about the data model without having to see the actual graphic.
So, we could clean up your existing model like:
Offer{
id:string
title:string
groups<-->>Group.offer
}
Group{
title:string
displayOrder:number
offer<<-->Offer.groups
items<-->>Item.group
}
Item{
title:string
displayOrder:number
isSelected:Bool
group<<-->Group.items
}
Now if you read a keypath in code that goes AnOfferObj.groups.items you can instantly tell you are traversing two to-many relationships without knowing anything else about the data model.
I am unclear exactly what you want your "Evaluations" to "copy". You appear to either want them to "copy" the entire graph of any Offer or you want them "copy" a set of Item objects.
In either case, the solution is to create an Evaluation entity that can form a relationship with either Offer or Item.
In the first case it would look like:
Evaluation{
title:string
offer<<-->Offer.evaluations
}
Offer{
id:string
title:string
groups<-->>Group.offer
evaluations<-->>Evaluation.offer
}
... and in the second case:
Evaluation{
title:string
items<<-->>Item.evaluations
}
Item{
title:string
displayOrder:number
isSelected:Bool
group<<-->Group.items
evaluations<<-->>Evaluation.items
}
Note that in neither case are you duplicating or copying anything. You are just creating a reference to an existing group of objects. In the first case, you would find all the related Item objects for a particular Evaluation object by walking a keypath of offer.groups.items. In the second case, you would walk just the keypath of the items relationship of the Evaluation object with items.
Note that how you ultimately display all this in the UI is independent of the data model. Once you have the objects in hand, you can sort or otherwise arrange them as you need to based on the needs of view currently in use.
Some parting advice: Core Data is not SQL. Entities are not tables. Objects are not rows. Attributes are not columns. Relationships are not joins. Core Data is an object graph management system that may or may not persist the object graph and may or may not use SQL far behind the scenes to do so. Trying to think of Core Data in SQL terms will cause you to completely misunderstand Core Data and result in much grief and wasted time.
Basically, forget everything you know about SQL. That knowledge won't help you understand Core Data and will actively impede your understanding of it.
I have a class Question which has a lot of assocated models. On one page on my app i list a summary of all the current questions, with various info from associated records. Ultimately this is a hash of values that i then just print out into a csv-style row (i'll call this the 'row hash' from hereon)
I now have a requirement to only show the changes to questions (or their associated data) over a given period. I'm currently deliberating the best way to do this. Here's some ideas i've had so far, i'd welcome any feedback, thoughts, suggestions etc.
1) Approach 1 - acts_as_audited
This was my first thought as i've used this before in other apps. The porblem with aaa though is that it only tracks changes to the record's data (ie it doesn't care if the associations change). So, i could audit all of the associated records as well but then trying to piece together what had changed by tying different audit records together sounds like a nightmare.
2) Save the old and new hash out into serialized fields: ie
- when someone goes to the question/edit page, i calculate the current row hash and save it in a serialized field "old_data" in the question table. Then after they save the question i calculate the new current row hash and save it into a serialized field "new_data" in the question table. Also, i compare the two serialized hashes and save the differences into another serialized hash field 'changes'. Now to do my report i just look for questions updated in the last x days and output their changes data.
3) make a view
- i make a view which corresponds to the data that i want to output (ie that amalgamates all the data that i pull into my report). Then i track changes to the view - somehow. I'm not sure how exactly i would do that.
I'm leaning towards option 2 right now.
Any other thoughts/comments? grateful for any suggestions - max.
So, like you said, you only want to show changes to the records between time x and time y, right? This would seem perfect to me using the acts_as_audited plugin because you end up with a table of changes, right? So make a has_many_through association from Question to all these related tables, then search it for related changes, where date created is after time X. This would return a list of changes. From there, you could connect this list back to the parent object if you need to, or whatever - but it in the end seems like a more reasonable thing to search. You're not looking for a list of related objects, after all, you're looking for a list of changes, so having a table of changes seems a reasonable way to accomplish that?
Hey I had a similar problem, check this out. If you can, go with Mongoid or Mongomapper, embedded versioned documents are sweet.
Thanks guys. I ended up rolling my own solution because what i really needed to do was to capture changes in the results of various methods called on the object, some of which involved associated objects. I wasn't so much interested in the associated objects as (for example) a text string generated as a result of looking at a few different associated objects. I had methods to do all of this already so i really just needed to track changes in the results of calling these methods.
None of the plugins i saw could really do that simply and effectively, so i ended making a table called states which just holds a serialized hash with results of all of these method calls. This gets saved when the record is altered and saved or when any of the relevant associated objects get altered and saved. Then i have some methods to return the differences between different saved state records. It works well for my needs. Thanks very much for your advice anyway.