Rails save record draft with dummy variable - ruby-on-rails-3

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.

Related

How do I batch update my app database?

New to MVC and RoR and having a hard time grasping some of the concepts. One of them is batch updates to the database.
Lets say I have a set of data such as a list of students and their attributes like this
Student ID:1
Name: Alice
email:alice#alice.com
attribute: anything
attribute2: anything2
Student ID:2
Name: Kate
email:kate#kate.com
attribute: anything
attribute2: anything2
etc..
I've gotten the list from an API call.
I don't want them to be editable, nor do I want the attributes to be visible to the user.
Question is, how do I go about saving them into my database? It seems in the MVC way, each action requires a view? Will I be able to do it as a background process?
Thanks
Ryan
p/s- pointers to the right resources welcome too
So you'd just like to obtain records from an API and create models from them?
One option you may consider is writing rake tasks to get the data, and create the corresponding models (No rails answer is complete without a railscast link, so here's one It's old, but tells the basics)
Going this route, you could avoid making the data publicly editable, and just get it into the models/DB
You could use fixtures for this type of thing. Or, just use SQL to insert into your DB outside of Rails.
http://api.rubyonrails.org/classes/ActiveRecord/Fixtures.html

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.

Independent Indexes in Elastic Search

UPDATE: Redefined what I am trying to do.
I have a model of Contact, this contact belongs to an account as does every other model in my account. I need all searches whether they be global or model specific to only query the containing account. I was told that I could do this with custom index names. I would like the index name to be the 'index-#{account-id}'. How would I achieve this in my active-models?
class Contact < ActiveRecord::Base
include Tire::Model::Search
include Tire::Model::Callbacks
belongs_to :account
mapping do
indexes :first_name
indexed :last_name
end
end
class Account < ActiveRecord::Base
has_many :contacts
end
You may want to check this comment at Tire's issues, which basically walks through some possible scenarios of the “tenant-based” index naming with Tire. I believe it's what you're after.
In elasticsearch itself, you have the option to have a separate index for every account, a filtered & routed index alias for every account, index templates, etc etc., so the toolkit is vast in this area.
Do you refer to having each account (user?) physically separate in each it's own index? This is generally referred to as 'multi-tenant' http://en.wikipedia.org/wiki/Multitenancy
Assuming this is indeed what you set out to do:
Much has been said in the past about the 'need' (I assume you want this for security reasons, I'm not familiar with other reasons why you would want this although I'm not an expert with multi-tenancy apps) for partitioning data per account/user, as apposed to just having, say, a field accountid for Contact and be sure all your queries filter, at least, on accountid. IMO, a carefully designed query-component where, say, every query used in the system inherits from a 'super-query' which is required to set accountid would suffice in a lot of cases.
Even if you don't know upfront what apps in the future will want to query these indices, you could still enforce the above by say, having a thin REST-service around ES and require all programs to interact with ES through this service. You could then have this service handle this type of security by enforcing an accountid or, probably better, by inferring the accountid by the current logged-in user doing the request.
If you still want to pursue Multi-tenancy have a look at: http://elasticsearch-users.115913.n3.nabble.com/Multi-tenacy-td471400.html (quickly searched this, perhaps there's better stuff around) 'Kimchy' (the creator of ES) comments in that thread as well.
Regardless, the best way in ES to have multi-tenancy is probably to have 1 index per account/user . Within that you could have multiple 'types' (an ES construct) , where Contact could be such a type.
http://www.elasticsearch.org/guide/reference/mapping/
http://www.elasticsearch.org/guide/reference/api/search/indices-types.html
Enforcing this in your models, as you are suggesting, is probably not the correct way IMO. Generally, you should keep your domain-models clean from any knowledge on the storage backend (including the index in which the data is stored)
To me, a better solution would be to have, as earlier suggested, a query-component in which the logic of choosing the correct index based on account/user would be contained. Going with the rest-service approach above, the dynamic indexname, as you suggested, could be derived from the logged-in user doing the request.
I realize that this probably wasn't a straight answer to your question, but I hope it was useful nonetheless.

Is there a better way to do this than using a query string in rails 3?

I have two models, we'll call them Entry and Comments for our example, that are associated as Entry has_many :comments and Comment belongs_to Entry. When a new comment is created, I need to obviously supply the id of the Entry for the foreign key. Right now, I'm using a query string. It works like this. A user views and entry, clicks a link to create a new comment (the link looks something like b/new?a_id=1) and then I use the build method to create the new record.
I know if I nested the resources it'd work just fine, but there are reasons that I don't want to do that, namely that I plan to nest a resource under Comments and don't want to go so many levels deep.
I initially had the form for a new comment on the Entry show page, but was having problems doing some custom validations and passing the error messages, etc. (namely, I needed to count the words before submitting).
Any thoughts? I'm not opposed to using query strings, just not sure if there's a better way.
I honestly can't see the problem with nested resources. You're going to have to identify the Entry in your case so your choices are POST /entries/123/comments or POST /comments?entry_id=123. Personally I prefer the former.

Am I breaking my aggregate boundaries in this model?

I'm modeling a very basic ASP.NET MVC app using NHibernate and I seem to be stuck on my design. Here's a sketch of my model:
As you can see this is VERY basic but I have some concerns about it. The User root entity and the Organization root entity are accessing the same Organization_Users entity child via two one-to-many relationships. This doesn't seem right and I think I am breaking the aggregate boundaries. This model smells to me but I like the idea because I would like to have code like this:
var user = userRepository.Load(1);
var list = user.Organizations; // All the organizations the user is a part of.
and
var org = orgRepository.Load(1);
var list = org.Users; // All the users in an organization.
Also the extra data in the table like flagged and role would be used by the Organization entity. Is this a bad design? If you have any thoughts that would be great. I'm still trying to get my mind around the thinking of DDD. Thanks
This is a typical Many-To-Many relationship. And the Organization_Users tables is the bridge table. Infact NHibernate and all the other ORM tools have built-in feature to support bridge table.
This thing should be resolved at data modelling level rather than at application level. You should analyze your data model and it is recommended to avoid many-to-many relationships (in the sense if it is not the necesity of domain model, you should try to avoid many-to-many relationship).
First thing first you need to be sure that many-to-many relationship in data model is necessary for mapping domain entities. Once you have done this then the model represented in your diagram is ok for mapping those relationships at application level
I have used an approach similar to your first model on several occasion. The one catch with this approach is that you need to create an OganizationUser class in your domain to handle the Role and Flagged fields from you Domain. This would leave you with something like this in your code.
var user = userRepository.Load(1);
var list = user.OrganizationUsers; // All the organizations the user is a part of including their role and flagged values.
var organization = list[0].Organization;
*If you're going to be iterating through all a users organizations quite often you'd likely want to eager load the Organization entity along with OrganzitionUser
With the second design you submitted it looks like you would be able to add a user to the OrgUserDetails without adding the user to OrganizationUser. That doesn't seem like something I would want to support from my Domain.
The first things to consider in DDD are :
forget your database schema (there's
no database !)
what actions will you perform on thoses entities from a domain perspective ?
I think your model is fine. I usually think of domain aggregate roots, when I think of them at all, in terms of what is publicly exposed, not internal implementation. With relationships I think of which entity "wears the pants" in the relationship. That is, is it more natural to add a User to an Organization or add an Organization to a User? In this case both may make sense, a User joins an Organization; an Organization accepts a User for membership.
If your domain sees the relationship from the User's perspective, you can put the methods to maintain (add, remove, etc.) the relationship on the User and expose a read-only collection on the Organization.
In response to your second design (it would have been better if you had edited the original question): I don't like it at all. Your original design is fine. I wouldn't necessarily ignore the database while designing your classes, a good design should accurately model the domain and be straightforward to implement in a relational database. Sometimes you have to compromise in both directions to hit the sweet spot. There's no jail term for breaking aggregate boundaries. :-)
My understanding is:
A User can belong to 0-to-many Organizations.
AND
An Organization consists of 0-to-many Users.
Are both of those correct? If so, that does sound like a many-to-many to me.
In a many-to-many, you pretty much need a relationship-like object of some sort to bridge that gap. The problem is, there is no user_organization in the domain.
This makes me think you shouldn't have user_organization as a part of your domain, per se. It feels like an implementation detail.
On the other hand, maybe it makes sense in your domain to have a Roster which holds the Users in an Organization and stores their role and other information specific to that relationship.
Thanks everyone for your answers. They have been very helpful.
While I was thinking about my model a little bit more, I sketched something new that I think would be better.
My thinking was this:
When a user logs into the site the system finds their account and then returns a list of organizations they are apart of and it gets this info from the user_organizations object.
When a user clicks on one of the organizations they are apart of it directs them to the organization's control panel.
The selected organization then looks up that user's role in its org_user_details to know what access the user should have to that organizations control panel.
Does that make sense? :)
I feel like that would be good in a model but I'm having some doubts about the DB implementation. I know I shouldn't even worry about it but I can't break my bad habit yet! You can see that there is kind of duplicate data in the user_organizations object and the org_user_details object. I'm not a DB pro but is that a bad DB design? Should I instead combine the data from user_organizations and org_user_details into a table like the one in my first post and just tell NHibernate that User looks at it as a Many-to-Many relationship and Organization looks at it as a One-to-Many relationship? That sounds like I'm tricking the system. Sorry if I seemed really confused about this.
What are your thoughts on this? Am I over thinking this? :P