How does OOP translate to Rails? - ruby-on-rails

I'm having a hard time wrapping my head around Rails' MVC system and its relationship to Ruby classes. In Rails, it feels like objects go out the window and are replaced by databases.
I'm working on an interview question right now and it requires me to create a website that accepts HTTP requests and returns responses. I'm not super familiar with JS and I like Ruby a lot so I've been using Rails. But I feel so limited by the database... it feels like things that I could do so easily in Ruby (e.g., look through a hash of objects and filter by multiple constraints until I got what I wanted) are so much more difficult with a database.
The interview question says I don't need to use a durable data store, but that seems like a big no-no in Rails. Does anyone have advice for how to change my mindset around this? (Or, in the short term, recommendations for other easy-to-use tools?)
BTW - I know this may beg the question, "why are you interviewing if you don't know this stuff?" It's an internship and I'm just trying to start interviewing as much as possible so I get used to the process.

But I feel so limited by the database... it feels like things that I could do so easily in Ruby (e.g., look through a hash of objects and filter by multiple constraints until I got what I wanted) are so much more difficult with a database.
Working with databases is challenging since SQL is a completely different paradigm. Instead of being object oriented SQL is based on tables and relational algebra.
Everyone finds it easier to hack out loops and create if/else constructs to munge data as a beginner. But its not really a viable solution at scale. Any time you spend learning SQL will pay off immensely in the future.
I'm having a hard time wrapping my head around Rails' MVC system and its relationship to Ruby classes. In Rails, it feels like objects go out the window and are replaced by databases.
This doesn't really have that much do with Rails or MVC. Its rather ActiveRecord which is the object relational mapper (ORM) which is built into Rails by default.
In comparison with other ORM's ActiveRecord has a lot of magic. It reads your table definitions from the database and automatically sets up attributes - in other ORMs you do this explicitly in your model classes, a repository class, XML files or annotations. This magic is great for productivity but can be very difficult to wrap your head around as a beginner.
ActiveRecord is still very much an object oriented design - just with more metaprogramming then you may be used to.
The interview question says I don't need to use a durable data store,
but that seems like a big no-no in Rails.
This is a misconception. Rails is a very modular framework and can be used without ActiveRecord, with other object relational mappers (or object-document mappers) or even without any storage at all.
Models are also are not necissarily even persisted at all. They are just objects that encompass the buisness logic of your application.
Most beginner guides start with ActiveRecord as an overwhelming majority web applications use a SQL database*.

I agree that this is probably one of the hardest things newbies face in Rails. In the Rails guide, models are almost always Active Record models (aka map to a database table). However, it's totally normal that not all of your models are Active Record models and / or need to be persisted. I think the term you're missing are Plain Old Ruby Objects (PORO) and Active Model.
A PORO could be anything from something super simple, a mapping to an API or composing several other (ActiveRecords) models together.
For example, you could have a versions controller which displays the latest version of your web app. The version would be determined by reading the SHA from the git repository, file or env variable. So it would never be persisted in the database.
class Version
def self.from_git
new(`git rev-parse HEAD`)
end
def initialize(name)
#name = name
end
def to_s
#name
end
end
class VersionsController
def show
#version = Version.from_git
end
end
Here are some links you might find useful
https://www.codewithjason.com/code-without-service-objects/
https://www.oreilly.com/library/view/build-chatbot-interactions/9781680507089/f_0047.xhtml
https://thecodest.co/blog/hi-im-poro-2/
https://www.toptal.com/ruby-on-rails/decoupling-rails-components
https://guides.rubyonrails.org/active_model_basics.html
https://www.codewithjason.com/extracting-tidy-poro-messy-active-record-model/

Related

RDBMS and Graph Database on the same Rails application

I'm developing a web app that has several "subapps" inside it. For some of them a RDBMS is clearly the weapon of choice. The issue is that lately I came with an idea for a nice little subapp whose logic and performance would benefit greatly from using a graph based database.
My problem is: This subapp is important and graph is the way to make it happen. On the other hand, the others are just fine on a RDBMS and in some cases migrating them to graph would add unnecessary complexity.
So, is it possible to have two heterogeneous database systems running on the same Rails app, perhaps using each controller to specify where to connect?
This is absolutely possible, but it's not something you'd handle at a controller level: it is the responsibility of each model class to define how its data is stored, for example by subclassing from ActiveRecord::Base or including Mongoid::Document or Neo4j::ActiveNode.
There's nothing particular you need to do. As long as the objects all conform to the active model interface (the above all do) then things like link_to 'Person', #person will still work.

In-memory ActiveRecord for production use

I'm currently extending some functionality from Redmine 1.4 issue tracker (it uses Rails 2.3.14 and Ruby 1.8.7).
One thing I don't really like about it for my current use case is that some classes that encapsulate business logic (roles, workflows) are database based instead of code based - our customer shouldn't be able to change roles and workflows without our intervention, and while I could just preload a pre-baked set of db data with the roles and workflows I want, I still think it would be a solution which is not the best for maintainability's sake.
What I'd like to do is something like that:
class Person < SomeInMemoryActiveRecordBaseClass
end
p = Person.new(:name => "Somebody)
p.save
And then I'd like to be able to invoke ActiveRecord methods on any Person object and from the Person class, even though there's no real database behind it.
This may seem a silly thing to do (If I were creating the project from scratch I'd simply not use an AR-based object, but since I'm building on something that already exists this is not an option), but the objects I need to work with in-memory are used in plenty of places and they're supposed to be AR-based; changing their usage everywhere would really be time consuming.
I've seen some projects, like nulldb, which are test-oriented, not production-oriented, and they don't implement all methods. Besides that, the AR interface seems quite sql-oriented and I don't know if it's really feasible to get an sql-emulation layer "right".
Is there any library that could suit my use-case of creating a fully-functional activerecord in-memory database?
(I've already thought about using a different connection and leveraging an inmemory sqlite db, but it seems a bit overengineered to me).

How to use around_filter to scope all queries in Rails?

My Problem
We are developing a locally-hosted web application for small businesses. We also have a demo site that lets potential customers look around to evaluate the product. Right now, all customers using the demo site have access to the same data, which is less than ideal because they might be making modifications behind each others backs, which would make the app feel "unstable" if they noticed. I would like to give each customer their own data subset to improve their experience. Adding a user_id column to all my models is easy enough, but now I need to make sure all the queries use this new association.
The Hard Way of Solving My Problem
I could go through by hand and change a call like #people = Person.all to #people = current_user.people, but lame! Development is continuing on the master branch, and I don't want to have to babysit every query when I merge over to the demo branch.
What I'd Like to do Instead
I would like to do create an around_filter in my application_controller that will grab my queries and add in this extra layer of scoping like so:
around_filter :scope_on_current_user
def scope_on_current_user(&block)
MagicalClass.scope_on_user(current_user, &bock)
end
This is an idea I got from octopus, which is a database sharding gem. I've looked around in their source code, and it looks pretty hairy. They pretty much go elbow-deep into ActiveRecord, hijacking the DB connection, etc. I'm hoping that is overkill for what I want. Any advice on how MagicalClass might work? :)
Rails 3.1.0
ActiveRecord 3.1.0
There are patches to allow default scopes to take procs see here for details, and it may work now without any of the patches/gems.
That combined with Thread.current may be enough to get you going.
That said... might it make more sense to take a multi-tenant approach with separate DBs altogether?

Rails security concerns

I am a Java programmer mostly, and it's actually amazing that we don't have to worry about a lot of security concerns that php or even rails developers have to worry about. We have to worry about them, but I think our job is actually a lot easier. You just use Java (already big bonus points there) and use Spring with Spring security... and you're basically done. Java and servlets are actually really good in this respect.
Now that I'm working in Rails, I think the biggest security concerns that I am the most scared of are parameters - both in the ones that are coming from the controllers (since they dynamic hashes, unlike in SpringMVC) and having to include more hidden values in forms.
But that got me thinking - you really have to be careful what you accept when you create new models or even update models. If you just blindly pass in parameters to your models, bad things can happen. In fact, things like the user role and stuff could be changed if you're not too careful.
It's almost like I want to write the setter code by hand to make sure it's not overwriting something that it shouldn't. And even if there's a framework mechanism to handle this... I would still want to test every risky model attribute just to be extra sure that it won't get overwritten on a create and on an update.
As much as Java gets a bad rep about productivity, it feels like it handles this stuff a lot better.
Anyway, my question is - what is the best resource/tips/advice for dealing with common security pitfalls/concerns/gotchas using rails - especially geared towards a Java/Spring developer who got used to working in a more stateful environment.
Even better, what would be a good checklist to go through every once in awhile?
And last, what tests would you recommend to make sure things are solid?
At least for your concern about assigning data to your model objects without proper checking, look into the attr_accessible declaration; it allows only specified attributes to be assigned via the bulk assignment:
user = User.new(params[:user])
user.approved = params[:user][:approved]
user.role = params[:user][:role]
You might find the entire 27th chapter of the Ruby on Rails 3rd edition book useful. (I haven't updated my 4th Edition book yet, not sure which chapter to recommend from the newer book. :)
I don't use ActiveRecord (I use DataMapper), but as a rule, I never do mass-assignment and I always expressly pass only the attributes I want to change. Rails 3 defaults to escaping all content in your views, unless you expressly output that data raw into into the .erb.
Also, it really bugs me that ActiveRecord doesn't help you out very much if you need to drop down to using SQL for something. You have to escape input yourself, which can expose you to the risk of human error allowing arbitrary SQL to be executed in your queries. DataMapper's underlying DataObjects connection supports prepared statements out of the box and in fact, it would actually require more work to avoid using them.
Rails 3 does have CSRF protection turn on by default too. It also makes session cookies HTTP-only by default, which makes them harder to steal via JavaScript.
I actually think, aside from Rails encouraging the use of mass-assignment, you're pretty well-covered for security.

How to create a user customizable database (like Zoho creator) in Rails?

I'm learning Rails, and the target of my experiments is to realize something similar to Zoho Creator, Flexlist or Mytaskhelper, i.e. an app where the user can create his own database schema and views. What's the best strategy to pursue this?
I saw something about the Entity-Attribute-Value (EAV) but I'm not sure whether it's the best strategy or if there is some support in Rails for it.
If there was any tutorial in Rails about a similar project it would be great.
Probably it's not the easiest star for learning a new language and framework, but it would be something I really plan to do since a long time.
Your best bet will be MongoDB. It is easy to learn (because the query language is JavaScript) and it provides a schema-less data store. I would create a document for each form that defines the structure of the form. Then, whenever a user submits the data, you can put the data into a generic structure and store it in a collection based on the name of the form. In MongoDB collections are like tables, but you can create them on the fly. You can also create indexes on the fly to speed searches.
The problem you are trying to solve is one of the primary use cases for document oriented databases which MongoDB is. There are several other document oriented databases out there, but in my opinion MongoDB has the best API at the moment.
Give the MongoDB Ruby tutorial a read and I am sure you will want to give it a try.
Do NOT use a relational database to do this. Creating tables on the fly will be miserable and is a security hazard, not just for your system, but for the data of your users as well. You can avoid creating tables on the fly by creating a complex schema that tracks the form structures and each field type would require its own table. Rails makes this less painful with polymorphic associations, but it definitely is not pretty.
I think it's not exactly what you want, but this http://github.com/LeonB/has_magic_columns_fork but apparently this does something similar and you may get some idea to get started.
Using a document store like mongodb or couchdb would be the best way forward, as they are schema-less.
It should be possible to generate database tables by sending DDL-statements directly to the server or by dynamical generating a migration. Then you can generate the corresponding ActiveRecord models using Class.new(ActiveRecord::Base) do ... end. In principle this should work, but it has to be done with some care. But this definitely no job for a beginner.
A second solution could be to use MongoMapper and MongoDB. My idea is to use a collection to store the rows of your table and since MongoDB is schema less you can simply add attributes.
Using EntryAttributeValue allows you to store any schema data in a set amount of tables, however the performance implications and maintenance issues this creates may very well not be worth it.
Alternately you could store your data in XML and generate an XML schema to validate against.
All "generic" solutions will have issues with foreign keys or other constraints, uless you do all of that validation in memory before storage.

Resources