Rails polymorphic associations and database queries - sql

I've a problem with a couple of polymorphic associations. I'm trying to connect both Users and Recipes to shared Dietary Requirements (DRs) through polymorphic associations, with the dietary requirements available to many-to-many of each.
I've created a Dietary Requirement to test this (Vegetarian), though am having trouble accessing this in the page view. I think the reason for this is that the DR created has the classifiable_type Recipe, meaning when the database query runs, I can't access this particular instance for my Users as SQLite automatically looks for a classifiable_type of User. Also, as it stands, each DR appears to have to belong to a specific User or Recipe, while I'd like them all available to many (or am I wrong here?)
In the console, I can see both User.first.dietary_requirements and Recipe.first.dietary_requirements, though in the view I can't access these, because of the reasons above.
Is there a way to circumvent this problem and get my view showing a list of User DRs and Recipe DRs, or will I have to adjust my models to achieve this? Right now I'm planning to switch to more verbose has-many-through relationships, with separate join tables between User - DRs and Recipe - DRs. If there's an alternative, Rails-way to achieve this, it'd be great to hear.
Model code below:
Recipe
has_many :dietary_requirements, as: :classifiable
User
has_many :dietary_requirements, as: :classifiable
Dietary Requirement
belongs_to :classifiable, polymorphic: true

You would need Dietary Requirement to have has_and_belongs_to_many relationship with Users and Recipes, however you cannot have polymorphic HABTM associations. You will need to create a join model for it to work.
More: HABTM Polymorphic Relationship

Related

Rails Uniqueness: true model with a DB with has_many references - Ruby on Rails

I have a problem. I need to set a model of report_templates unique in my database in relation to the classroom, each classroom has only one report_template.
But in my DB, I already have a classroom with multiple report_templates.
is it safe to add this validation to report_template model upload to staging?
There are two approaches:-
If you add validation then you will get error when you are editing existing report templates. This is because validations are called when you save the record. So you might have to remove the duplicate/multiple records manually via console or db or a rake task.
Simply accessing the record will not throw an error.
If one classroom has only report template do you think it is better to use either of below? I do not know the exact scenario so cannot suggest an approach.
has_one association
belongs_to association
Thank you.

Rails save record draft with dummy variable

So I need more alongs the lines of just advice than actual code here, but this is my situation:
I have a model that requires two associations - an author and a user. However, I want it to be possible for authors to create the record with the possibility that it will later be "claimed" by a user created later.
The best solution that I've come up with is to user some sort of "Dummy User" association for those cases, but it feels hacky.
Any better suggestions?
How about making the associations not required? Are the associations enforced with validations? How about relaxing the validations instead? So there would be no user association persisted until the time it is claimed.

ORM: authorization via reachability

We are building a webapplication which uses a database. Also we use an object relational mapper to access the database. One aspect of authorization in the webapplication is that the user may access an object referred to by an URL. The URL contains a unique id (for example the Primary Key) to a specific record in the database. Consider the following example.
a user may belong to many groups and a group may have many users (many-to-many).
a survey belongs to a group (many-to-one).
a survey may have multiple questions. (many-to-one).
Say we have the following URL: http://app.local/question/edit/10. This means we want to edit question with PK 10. Now, we want to verify if the logged in user may access question with PK 10. This can be done by retrieving this question, then it's survey then it's group and then all its users. If any of the users is the same as the logged in user the logged in user may access the question.
To generalize this a bit; we want to check if a record is reachable from another record by the known many-to-one or many-to-many relations. So if there is a many-to-one relation (like with a survey and a question then we should check if a user is reachable from the question through the survey and then through the group. The group has a many-to-many relation with the user so we should check if any (not all) of the users is the same as the logged in user.
If a table has multiple many-to-one relations, say; we can attach a CSS template to a survey and this template also belongs to a group then we have to check if a user is reachable from all many-to-one relations (thus the group and the template). The same holds of course for multiple many-to-many relations.
Are there Object Relation Mappers which support this behaviour? And what is this behaviour called, maybe reachability? Does Propel (for PHP) support this behaviour? I think this reachability can be done in any of the following two ways:
Execute a query to get each "parent", uses many queries)
Join all necessary tables to see if a record exists (the reachable users matches the logged in user) in one query.
Furthermore this behaviour of the ORM should support nested sets, thus if a group contains nested set behaviour it should also try to reach a user through the group's parent.
I don't think this kind of behaviour should be restricted to authorization; objects should simply be able to see if they can reach another object.
Note that I do not mean persistence by reachability: http://jpaobjects.sourceforge.net/m2-site/main/documentation/docbkx/html/user-guide/ch08s03.html.
Or... am I simply looking at this authorization wrong and is there a far better and different approach with an ORM?
I've handled this in the past using nested resources in Ruby on Rails (which uses the Active Record ORM). Rather than http://app.local/question/10/edit, the URI would be http://app.local/survey/5/questions/10/edit
In the controller you load both the question and survey. You check authorization by comparing the survey to the authenticated user's group memberships. One way to engineer this would be to embed this logic into the User class. For example, in the controller you have question and survey (and the relationship between the two is well understood by the ORM, i.e. question.survey). You could then check access as user.hasAccess?(question), which would be a relatively easy method to write. Pseudocode:
class User < ActiveRecord::Base
def hasAccess?(question)
return question.group.users.include?(self)
Yes, this will result in several queries behind the scenes, but ORMs do the work. I do it this way because you're left with solid schema and easy to read code. Don't optimize until you actually have a performance problem.

Mother/Father/Children relationships in Rails

I am pretty sure this is a pretty basic question. anyway I don't find the right information to get going.
I have got 3 models.
Users - Tasks - Notes
Users and Tasks are on the same level, as tasks are children of the Projects model, and they function as a template.
Then for each user I display all the tasks of the project and add notes.
Notes in this case are children of BOTH Users and Tasks, actually they are children of the combination of the two.
What is the best way to tackle this problem? I checked out polymorphic associations and doesn't seem it will work in this case.
Cheers,
Davide
From what I understand of your problem polymorphic associations are exactly what you want, being that Users have many Notes, and Tasks have many Notes.
The relationships would look like this
in both user.rb and task.rb
has_many :notes, :as => :noteable
in note.rb
belongs_to :noteable, :polymorphic => true
in your create notes migration
t.references :noteable, :polymorphic => true
Note both Users and Tasks can have Notes, and Notes can belong to either a User or a Task (or anything else that connects using the noteable polymorphic interface).

Rails 3 - Many to Many - How would you do?

I have found lots of answers on StackOverflow but i'm kinda stuck on this one
I'll try first to describe with words what I have to do:
I have multiple applications, each application can have one or multiple profiles (one to many).
I also have users, who have access to each applications through the different profiles. Each profile can have multiple users (many to many).
up to here no problem, i can get all profiles a user has been granted.
However, the difficulty here is that for each profile coming from an application, the user has a username, specific to each applications. When i see the details of a user, i want to see a list of all the profiles he's in together with the username he has been assigned for each application...
I'm sure there an easy way to do this with rails, as usual, but i can't seem to find it. How would you do this ?
So to make sure I've got this: an Application can have many Profiles, and Users can have many Profiles. So this isn't a simple many-to-many relationship between Application and User because the Profile is a first-class object.
Rails handles simple many-to-many relationships with the has_and_belongs_to_many (HABTM) association, declared on the models on both ends. What's in the middle is unimportant and merely serves to join (relate) the two models.
Your case is more fun. Your many-to-many is described in Rails as "has_many :through", and I think your case is a very good example of such a case. In this case, Application and User each have many of the other through the Profile model. Profile isn't there just to link the two, it holds username, and probably many other details of the User's relationship with his/her Applications.
Start with this excellent guide which should show you how (and why) to choose has_many :through and how to get it all modeled and set up. This is (as you suggest) one of the absolutely brilliant capabilities of Rails.
I hope this is helpful.