Creating unique association with Rails - ruby-on-rails

How to create an unique association (many to many) with Rails ?
Ive :
article +-----+ article_user +------+ user
I want that the user can mark only one time an article, not twice or more.
How can I do that ? I Tried with uniqueness it doesn't work.

Sounds like you're looking for a composite primary key - so that a combination of article and user is always unique in your joining table.
Last time I check this isn't natively possible in ActiveRecord - you might want to try something like this:
http://compositekeys.rubyforge.org/
Stu

Related

How to handle product/subproduct in Rails 4

I am making a proof of concept for an app, using Rails 4 and Postgresql. I am thinking on the best way to handle the relation between Products and SubProducts.
A Product have a name, a description... and a SubProduct could have multiple fields too.
A Product have many SubProduct, a SubProduct belongs to one Product.
I have some Products and SubProducts with hundreds of fields. So I think it is best to not use STI to avoid thousands of null value.
Also I am working with remote designers, I would like to keep it simple for them. So when they want to display the value of a field from a sub product, they would write something like #product.name (from Product table) or #product.whatever (field from SubProduct table).
My question is how to handle this ? For the moment, I was thinking to delete the Products table and to make multiple SELECT to db, one for each SubProducts table. But maybe there is a solution to keep the Products table ? Or maybe I can take advantage of table inheritance from Postgresql ?
Thank you :-)
Are the hundreds of fields all different for each subproduct? (As you mentioned, "sparse" attributes can lead to lots of nulls.)
This brings to mind an entity-attribute-value model, as described here:
https://en.wikipedia.org/wiki/Entity%E2%80%93attribute%E2%80%93value_model
Here's a presentation with one organization's solution (key/value hstore):
https://wiki.postgresql.org/images/3/37/Eav-pgconfnyc2014.pdf
This can quickly get very complicated, and makes things like search much more challenging.
And if there are many variations, this also brings to mind a semi-structured, document-oriented or "NoSQL" design.

Rails relationship with a relationship

I have a user and a merchant that have a relationship. I need to store information about the relationship, so I am using => through user_merchant_relations.
1) Is my naming convention incorrect? I've read some answers that indicate it might have to be merchant_user
2) Should I force the "join" / "through" table to NOT have a separate ID (e.g. only have the two foreign keys)?
3) In the relation table I reference a program_id. A User-Merchant relation can only have one Program ... but Programs will belong to many User-Merchant relations ... what is the correct way to handle this?
Thank you very much.
1 - The convention is that the models should be ordered alphabetically, so the name should be merchant_user
2 - It seems that with the logic you explained there will be no merchant_user with the same merchant and user at the same time, so you can skip the id. Remember to properly create the validations.
3 - It seems that Program has many MerchantUser and MerchantUser belongs_to Program

Three ways to use user_id in a rails database, which one is best?

I have a rails application linked to a database table, which contains e-mail addresses and passwords. I would like to create a unique number which will identify each of the users in the system. This number will be given to a user upon registration, and stored in the field user_id on the same table.
So, for example, john#foo.bar could get 0001 as an ID, martha#foo.bar could get 0002, and so on.
My question is: what is the best way to do this?
Should I seed the database (rake db:seed) with the first user_id (0001) and write a method in the controller to +1 the user_id every time? If that is the case, how can I access the last row in order to find out the last user_id?
An alternative way would be to find the largest user_id in the table and +1 it. For that I guess I need to use tablename.find_by_user_id or something similar (would tablename.find_by_user_id.max work?)
A third way would be to store the latest user_id somewhere, and have the application retrive it when needed. Where could this information be stored?
I'm very new to rails . Would appreciate your feedback about which is the best way to go.
Thanks,
TimmyOnRails
Lets assume your model has two attributes name and email. Now by default rails will generate three more columns for you
1 id - auto incremental
2 created_at and updated_at - timestamps
Rake db:seed is one of the good solution in case you want to prepopulate the database. All you need to worry about is name and email. Add proper validations for these attributes. Rest rails will handle ie id is maintained by rails itself. You don't need to worry about it. Created_at and updated_at columns are also maintained by rails.
If you new to rails then I will suggest you to check http://railsforzombies.com and that will you a good idea about active records
Railsguides and RailsCasts are also two other learning materials for rails.

Resource with a single attribute. Sign that something smells?

I have a book model and a notes model. Each book can have many notes.
# note.rb
id | book_id | content | page_number | author_id |
I want to run a lot of queries like
Get all the notes for page 43 of a certain book
Show all the noted pages of a certain book
These types of queries seem to favor making a separate noted_pages model so that a book can have many noted_pages and each noted_page can have many notes. This is fine but my noted_pages table would effectively just have an id column and a page_number column which doesn't sit right with me.
Is there a more standard way to implement this kind of setup or is my thinking ok?
A noted_page table would relate notes to pages, but do you need a page table?
If you need a page table, then yes, worry about the note<->page many-to-many relationship and create a link table. If you don't need to store book_pages as rows of a table, then don't.
Your design:
id | book_id | content | page_number | author_id |
Will give you the answers you want by querying like this:
Get all the notes for page 43 of a certain book
select *
from note
where book_id=123 and page_number=43;
Show all the noted pages of a certain book
select page_number, count(id)
from note where book_id=123
group by page_number;
If performance is an issue then put an index on the page number. You could also make (id, book_id, page_number) into a composite key, so your data will store (note 3, book 123, page 43).
If you want a many to many relationship, as in a book can have many notes, and notes can have many books, you must have a join table like you stated.
It would look like:
noted_page
--------------
id book_id note_id
This is just general practice, whenever you have a many-to-many relationship you MUST have a join table.
(Some frameworks/orm's don't require you to have a id column, but as far as I know, Rails/ActiveRecord does require it.)
No design is bad ... it just need to be justified.
I see different solutions :
A BOOK {title, author, edited_date ...} has many PAGE {content} has_many NOTES {note_content}
A BOOK {content, title, author, edited_date ...} has_many NOTES {note_content, page_number}
It depends on how you work with the book. Do you plan on saving the content of the book by pages or not ? If not, then can you find the page, and therefore the notes ?
Regarding your questions :
A model with one attribute is not the sign that it "smells". You can even have a 1-to-1 relationship, if it's justifier.
There's no "standard" way of implementing stuff. Like I said, it depends on how you work, on how you plan your users to use it (UI-wised), how you would store, etc....
You definatly won't need a many-to-many in your case ... rails provide enough tools t fetch from a model to its associations, w/ w/o conditions, etc...
Let me know if it helps.
Both of these can be simple ARel queries, no scope is required
The latter one is a simple check of the existence of the notes collection:
#book.notes.empty? #if there are no notes, it'll return true and vice versa
To get the book notes for a certain page:
#book.notes.where(["page_number = ?", page_number]) #where page_number is a variable, possibly a parameter
However, I do think you need to think through how you're going to model your data. Marcel has a good point.
Your design is fine. Don't over normalize. You'll probably just want to put an index on book_id, page_number on your notes table so you can do the lookup efficiently.

How to relate multiple models to one model that will rule them all, in Rails?

Let's say I have four completely independent models (Movie, Book, Game, Album) that control the types of things I have in my media collection. With them I can CRUD and tag individual albums, movies etc.
But I need to keep track, and do some stuff that is common to, all of them. So I figured I need an Item model that would give me a table item like this:
| id | item_id | item_type | status | possession |
+----+---------+-----------+--------+------------+
| 01 | 01 | 1 | 3 | 2 |
Where the status and possession bit would let me keep track of whether the item is new or used, with me or lent (to whom, in another table), etc, and the table itself would let me know how many items I have in total. All without touching the original four models and their objects, that I think should only have information about what they are, not what I can do to them. EDIT: Note that every time a movie or book is added, it also must update the items table with its related information.
I'm a newbie and I had some ideas on how to go about it, but none proved successful. I know it's a lot to ask but I would like to know, how can I accomplish this?
Any help will be appreciated, thanks.
The simplest way to do this is to use a polymorphic association.
You are describing polymorphic associations in ActiveRecord. Check out these URLs:
Railscasts - Polymorphic Assiciation
A Guide to Active Record Associations - Polymorphic Associations
Inheritance in Rails (in my opinion) leave a lot to be desired, as it only allows single table inheritance.
What I would do, is relate each of your models (Movie, Book, etc) to an Item in a 1-to-1 relationship.
class Book < ActiveRecord::Base
belongs_to :item
end
Edit: After taking a look at the polymorphic stuff (something I forgot that Rails had, to be honest), I think that might be more what you're looking for. My way would work, but I think the other way would work better.
quick comments on attribute names ...
"Status" is IMHO horrible. Maybe "Acquisition type".
"Item type" is not too bad, but "Media type" might be more appropriate.
Here is a very comprehensive "state of the art" guide on entity naming conventions that would be worth skimming through at least. http://www.uscg.mil/directives/ci/5000-5999/CI_5230_42A.pdf

Resources