Web-based form-builder for users in Ruby/Rails - ruby-on-rails

First time posting in Stack Overflow, hope I'm doing this right.
I'm writing an app with Ruby on Rails right now. Without disclosing too much, the premise is that we have organizations and normal users. Organizations have events, which require users to answer a questionnaire before participating.
I'm pretty sure about these models / relationships that I will be using (this isn't really that important/pertinent to my question i think, but just wanted to give background):
organization (one to many) events
event (one to one) quesitonnaire)
questionnaire (one to many) users
(specific) response (one to one) user
The part I have a question about is how to implement the questionnaire. I want to give the ability to Organizations to essentially write / build their own forms. I'd like to stay away from them using code if that's possible (ie any DSL and whatnot).
I suppose the easiest way to do this is to give them a set number of text-area responses, so that I can consistently store the data and don't have to hassle around with how to configure storing this data (for example, maybe each event can only have exactly 5 responses to be filled in by textfield response by the user).
My ideal would be for the organization to be able to dynamically generate the forms on their own - maybe one questionnaire will have 1 text input, followed by 3 multiple choices, and maybe 2 short answers at the end; another one may have 5 multiple choices, and 1 short answer; yet another questionnaire might only have 1 text input...you get the idea.
So I see two parts of this problem - the first is the user interface for the organization to create the questionnaire. i'm imagining this wouldn't be terribly hard - ask them how many of each response type (MC, short answer) they would like to put into the form, give them the ability to rearrange them, etc.
The second part of the problem (what I'm more concenred about) is how to store/access this data. I'm guessing there's no dynamic-attribute sort of deal in ruby - storing some field with an unspecified number of parts and whatnot. i suppose i could make them all individual models (ie a question_response model, with :question, :response_type, :response, etc), but I'm fairly certain that's probably inefficient.
My initial guess is probably to serialize the data / use json; I worked briefly with Drupal 6 and this seems to be the way they did it. I was wondering if anyone else had any experience / suggestions though? I'm pretty new to Ruby so I was wondering if there's a gem out there or something that would help with what I'm trying to do.
Thanks!

You might want to look at the Surveyor gem
http://vimeo.com/7051279
*slightly old how-to video
https://github.com/breakpointer/surveyor
Surveyor does come with it's own DSL which is relatively easy to use (although can be abit restrictive at times). The data is saved as a set of question - answer values, so there is no actual specific model (beyond Surveys -> Questions (question_groups) -> Answers).
Originally I did look at having people submit their own Surveyor DSL specs - which would then be used to generate the actual survey via a Rake command.
I think if you need to build a dynamic model (and save the data) it is possible, although I am not not sure if you'll be able to get the Rake tasks to run to build the actual tables in a dynamic way due to permission restrictions.
Have a look at http://ruby-metaprogramming.rubylearning.com/ and Metaprogramming Ruby: Program Like the Ruby Pros by Paolo Perrotta, for some starters.

Related

What is the name of this concept I am implementing, and how to in Rails?

I am trying to implement a feature to my project (kind of like a social media site) that could be either basic or complex and I am not sure if I am going to take forever reinventing the wheel or just go on a crazy tangent that won't work. I just need to "check in" so to say.
I am going to use Facebook terminology as an example to simplify the concept but implement similar features with different names. In Facebook you have Pages and Groups, which are similar yet have slight differences (from now, I will call the collection of these DataSets). Both of these can have multiple admins or followers, which are all User roles, and each User can have roles for multiple Groups and multiple Pages (one role per Group or Page). Then for example, you can click a drop down to change your account to post as a Page you are an admin for.
Essentially, the concept I am describing is where a single User can have a role for multiple different types of DataSets. For example, a single User could follow 30 different Pages and 10 different Groups, and be an admin for one Group and two Pages. Does the concept I am describing belong to a particular concept or software design pattern? I am finding it really hard to describe this feature without using Facebook examples.
I have a strategy to implement this type of functionality in Rails, but I feel like using this strategy would be making the problem harder than it is and there is a fancy rails way of doing it, or a Gem, but I just don't know how to research it due to lack of terminology to describe my problem.
Current strategy is:
I have a Users table from Devise. Pages and Groups are each individual models and have their own tables. I have matching database tables to make the many-to-many relationships between Pages and Users, along with Groups and Users (e.g. 3 column design, column for the user_id, column for the page_id and the type of relationship such as admin or follower). Let's call these Group_User and Page_User. I am being flexible at the moment as I may add more DataSets similar to Page and Group.
Then for the Devise User table, I have an extra two columns to track the DataSet that the User is an admin for and currently posting as. One column is for the DataSet type and the other for the id for this instance (e.g. [Group,1] is stored in these two columns to represent Group with group_id:1 and [Page,3] is used to represent Page with page_id:3). These two columns can be checked when displaying options relevant for admins in that Group/Page and a simple drop down at the top of the site changes the values in these columns to any of the Pages/Groups the logged in User is an admin for. This way, one User login can take on many admin roles and change between these easily as needed.
Is there a better way to do this in Rails, such as a gem or specific design pattern? Or am I on track to implement these features myself? I think I understand the problem but my solution just seems simple/raw and possibly might have unintended consequences later down the track (e.g. it seems database intensive).
One way I was thinking of doing this was making a concern that includes methods to build the relationships and pass in the name of the DataSet as an argument, just so I am not rewriting the same methods for Pages, then Groups, then whatever comes next.
I looked at other solutions such as polymorphic typing (which I think is good for if each user only had one role or only managed relationships for one group or one page) and Single Table Inheritance (but I think my Pages and Groups might be too different for this to work). I thought about using inheritance as well (e.g. a parent for both Group and Page) but I am not sure this helps much.
I am just a guy that studied too much computer science and not enough software engineering. Any tips on how to simplify this problem or just a simple "yeah that will work" would be really helpful!
I think you are going great in the database design. Once participated in a social media application like yours which had similar type of design. Your design seems much better than the one I worked with. In my opinion this type of applications are supposed to be database extensive.
There are several design patterns used in RoR. One I heavily use is Service Object Pattern to maintain thin controller and models. Also it helps me to write reusable class.
Another one I like is the Presenter Pattern to simplify views.
You can have a details look at this blog post for more design pattern ideas.

Rails: Query using relation or directly using #where

I am from UI/ColdFusion background, sorry if I am asking a silly question.
Let's say we have two models Book & Page and a book has many pages.
Normally i see rails devs do the below,
book = Book.find(id)
pages = book.pages
Which indeed executes two queries, one for getting the book and one for getting the pages.
Where as the same we can write like this,
Add a class method to Page model.
pages = Page.where(book_id: id)
This will execute one query but will still return the result.
But then why developers prefers the first approach instead of the second.
It's just the practice people follow
Usually, this scenario comes when you are accessing nested resources
book = Book.find(id)
pages = Page.where(book_id: id)
so to make sure you have the book available not just the orphan pages
pages = Page.where(book_id: id)
Whereas, with the above query you will get the pages even if the book is deleted, in case you don't have the dependent: :destroy for pages
From my practice, there are 2 answers to your question and the right answer would depend on the developer's experience.
Novice - Because that's how it was in the tutorials. The first Rails team I joined had a lead developer with no DB or SQL experience. He would not care or knew about the load on db server our code generated. This was quite common in early days of Rails (in my experience). ActiveRecords makes it so easy to forget that you have a DB in the background and it is easy to forget. Coming from java and php world myself, I would be asking why would we just write an SQL to join and do the heavy lifting on the server side.
Experienced - Experienced developers do it for the code readability. Because maintaining a readable code is cheaper in the long run. If your monitoring tools show that your DB server started to stress out, you can always profile and fix it (vertical scaling, adding caches on different levels of your architecture, etc). Also, when used in the controller, .find will generate 404 page if it can't find the record in the DB. Also, if you run your "custom" sql, you will lose "automatic" model-data relation maintained by AR for you. So, many choose to just do it that way.
So there you go. Unless you are working on very heavy load application, it is better to write a readable way.

Data model and storage for Rails app

At the moment ’m building a web app using Ruby on Rails. I try to get my head around the data model and database part. To make it easy to understand I’ll use IFTTT as an analogy:
In the app, the user can add different recipes, for example:
Facebook — Twitter
Weather — Send email
You name it...
Of course every recipe has its own fields and options. So the user can choose multiple recipes from the library and set options to every recipe. The library of recipes is defined in code.
I have a few questions regarding this setup and would be happy if I could get some directions:
Is it smart to serialize the options of a recipe into a single database field? Every recipe has different fields and I don‘t want a database table for every recipe type.
Or is it better to create a ‘key-value’ table with all the options of all the recipes?
How to handle validation? Can Virtus come in handy?
Is a NoSQL database a good fit for these kinds of applications?
Are there best practices for these kinds of applications/data models? Any help is welcome.
Thanks!
Rens
Not sure if SO is the best place for really general questions like this but I'll take a swing
1 && 2) Personally I'd give the recipe table an action_taken field, probably as a string, and fields for all the available, resulting actions as booleans. Then the only thing you really need to be careful of is making sure the action_taken field remains uniform
3) ActiveRecord has a pretty fleshed out validation suite built in. You can validate based on presence, uniqueness, inclusion in a set of elements, etc. You can also extra validations on the database if you feel like being extra safe
4) I would use PostgreSQL, seems to be the community standard so probably the easiest to get support with if you need it
Hope this helps

Deciding between using an array attribute or a nested model

Possibly a fairly basic question, but bear with me.
I'm building a page which has a number of pieces of modular content, represented by a ContentBlock model. Each ContentBlock has at least one link, each of which has a couple of different attributes. My initial approach was to just add these links as an array to the model, as there didn't seem to be any real need to store them separately in the database, and they don't have any logic of their own. Now that I'm looking at building a form for creating/editing a ContentBlock though, it seems like it would be much easier to build if there was a separate, nested model for the links.
I'm strongly considering converting to using a model, but my gut feeling is that it's kind of "wrong" to store something like as relatively trivial as the links are in the DB. Given I am still getting used to working with Rails, is this feeling misplaced? Should I just create models for anything and everything? Or should I be looking for some sort of minimum criteria before I do?
It is definitely easier to create forms for nested models. Since your links have attributes, I'd suggest making a model. I tend to err on the side of making models for concepts that can't easily fit into fields. If you're worried about query performance, you can always do eager loading.
I think depends on how much data you plan on managing, what you want to do against that data, what that data represents, etc...
One project we had was to build something that allowed creation of recipes for a group of restaurants. Recipe (some text, like instructions, etc...) -> Ingredient, we went with an array, as these were all single lined text and there would never be more than several hand fulls. Also, the ingredients had no further dependencies. The Recipes would only be rendered out to html and there would be no searching against them (not against the db at least).
Another project required building a Page, very similar to yours, but each "component" of the page did different things and some where linked to other objects in the app, like Videos and other assets, templates, etc... We had seen people do this type of stuff entire through a wysiwyg or through some JS way and saved the entire payload/structure in the DB. We found both to be extremely messy.
And one concern that came up was what happened if an asset/associated object was mistakenly or purposely deleted but lived throughout many pages. Using models allowed to ensure that if something got removed, it got removed within all it's linked associations (though this posed problems of it's own, but more regarding the page making sense when displayed more than anything else).
Also, our Page had the potential of becoming extremely large with different types of components with different looks and inter-activities, that this really was the only way we could properly manage it.
So I would look at your requirements and plan accordingly, context matters. And if you have to change it (which happens, a lot) then you'll change it.

Considering a new Rails app with existing data (not a db, actual data) -- what is the best way to proceed?

I have been tasked with developing a new retail e-commerce storefront for my current job, and I am considering tackling it with RoR to A) Build a "real" project with my limited Rails knowledge, and B) Give management quick turnaround and feedback (they are wanting to get this done ASAP and their deadlines are rather unrealistic - I'm talking a couple of weeks to go from nothing to working model so they can start to market it with SEO/SEM and, I kid you not, "video blogging" because my boss heard that's the future).
We do have a database structure in place but it's absolutely terrible and was thrown together without rhyme nor reason, so I'm going to largely ignore it and create a new database from scratch; however, I have existing data that I need to load into the application (like I said, it's an e-commerce app and we have the product data). I need to massage this data into a usable format because our supplier provides it to us with cryptic, abbreviated column names and it's highly denormalized, especially in the categories (I've posted a question regarding it before - basically the categories table has six fields, one for each category/subcategory, with some of them being blank if that category doesn't apply).
There are two main issues that are giving me second thoughts:
As I said the data needs to be put into a "proper" database schema; I can't just load it as-is. I have some thoughts as to a good data model for it, but my analysis is not completed yet. There would end up being a large amount of joins tables to link various things together (e.g. products_categories, products_attributes, products_prices) etc and these tables would link products not via an ID but by their SKU (see below).
Everything already has an ID that's generated for it, but anything new I add needs to have one autogenerated; I doubt this will be a problem with any mature RDBMS, but I know Rails likes to generate IDs itself. Also, almost all of the product-related tables are linked by SKUs (and in the data provided by the supplier are actually a composite key consisting of the prefix and stock number, which combined make up the full SKU), not by IDs and I'm not sure if this will be a performance issue (of course, I could always manually create indexes on these columns to speed it up). It does mean that I'll need to break away from the Rails conventions, however.
In short, I think that Rails might be a good choice as far as time-to-market and ease-of-development, but having to work with the existing data content might turn into a pain because the application will need to be developed around that, instead of the "traditional" Rails app, and that factor is giving me major doubts about using Rails. There are also some other issues (having to set up a Linux server, and the fact that the area I live in has very few Rails developers so if I left the company I'd basically be holding them hostage as far as updates/modifications). I'm really unsure as to the best path to proceed.
I would develop the app as if you didn't have the data. Use the ORM and make your database the best it can be, but of course keep in mind what data you have to populate it with (eg: don't make crazy new constraints for things that will leave you going through old data record by record).
When you're done and tested, write an import script that pulls your real data onto your new database.
It's not that different from the conventional design/development model... Apart from you can do your data-input in a semi-automated fashion.
I was in the same situation not too long ago — a crappy PHP app that held ten years worth of all company data.
What I did was simply create a Migration model and added methods to import each resource.
class Migration
def migration_all
self.jobs
end
def self.jobs
...
end
end
The cool thing about this is that you can arrange which order resources are imported as one will likely reference another. I also added methods that directly modified the db schema. One nice trick if you have to keep an existing primary key is to create a field named 'legacy_id', copy over your existing primary key, and when you're done, simply remove the 'id' field, rename the 'legacy_id' field to 'id', then add the primary_key constraint on the new 'id' field.
Don't use the SKU as the unique key for each product - use the standard Rails incremented id.
SKU could change as it may be misentered, etc and that would make it a nightmare to change all of the references from other tables. Put your current id in a sku column, index it and update the references in your other tables to the Rails ids.
You'd be able to do Product.find_by_sku(params[:sku]) in your controllers, set up a /products/:sku route, etc. I don't see what you'd gain (other than a headache) by using your non generated ids as the database primary keys.
I'd also suggest running your old data through your app's validations to make sure you are not loading up a bunch of inconsistencies and erros. It will help your app run smoothly and highlight existing data errors at a point where you can fix them.
Don't assume the existing data is valid just because it is already there.

Resources