I'm writing an application that details an applicant's status in our company through Salesforce; when one of our employees enters their Enquiry ID, it shows their status (cleared, not cleared) and, if not cleared, what the applicant needs to fix before they can proceed in their program.
I want to make sure that I am thinking about my application's different areas correctly. Here is what I have:
Model: The applicant class has a dynamic function, such as Application.find_by_Enquiry_Token__c_and_Account_dot_LastName_from_Opportunity, and when requested it returns the information from Salesforce
Controller: Parses the returned data from Salesforce and creates hashes with the information, such as #applicant[:general_information] = {:first_name = data[:Account].first[:FirstName], :last_name = data[:Account].first[:LastName]}.
View: Displays the information generated by the controller. However, it has it's own logic and checks, such as changing the color of a div depending on if they are clear (class="success"), if they are not clear (class="danger") or if they have some conditional information (class="warning").
I think I have this correct, except I'm a little worried about my view because I have a bit of Ruby code in there to perform checks based on the returned data, mainly to colorize but also to show certain errors. Is this okay/does this follow standards? Or should I try to refactor my application and push this up to the controller?
I would say having some ruby code like you do in the view is fine as long as you aren't performing long queries or setting instance variables in the view. Also another sign to start moving code from the view to the controller is if you feel the view is getting cluttered and hard to understand. From what you said, this seems like it is not a problem though.
One thing I would recommend changing is to make the method name on the model shorter. Shorter method names are much easier to understand and as you have it, the method name is very long and unwieldy. Other than that, I think you are doing everything well!
Displaying the correct classes in the view is fine and can't really be done anywhere else. If you feel like your views are getting messy, consider dividing them into partials or using Haml for views instead of ERB.
Model is where your application's business logic goes, including parsing data, and everything related to your domain.
Controllers handle interactions with the user. So, basically, in a webapp if a user goes to a URL what should your application do. This should not be doing anything other than handing off tasks to other classes and then rendering a view.
Views are just that. They should be super simple and straightforward as possible. You can extract logic from views into helpers or even presenters/decorators. Views handle what gets displayed to a user.
In your app I would have:
SalesforceApiGateway class which handles communications with Salesforce, I wouldn't be surprised if there was already a gem out there to handle this.
A model class for each Salesforce resource you are accessing. These would setup the proper call to the API gateway to pull the right data for the given resource.
This could get hairy quickly and may need to be extracted further: 1 class for interfacing with the gateway and a model class the resources as you would want to access them from your application.
Your controller should not be parsing any Salesforce data, but rather taking a user request and and wiring that up to the proper model.
The biggest thing to keep in mind is your classes should be doing one thing and one thing only. If you can't talk about your class without saying "and" then it is probably doing too much.
So you have a class that interfaces with the API. You have a class that parses the API. You have a class that brings an api's resource into your domain, etc.
Related
Can anybody tell me the difference between controllers and actions in ruby on rails?
I fetched this definition from the official rails guide:
A controller's purpose is to receive specific requests for the application. Routing decides
which controller receives which requests. Often, there is more than one route to each
controller, and different routes can be served by different actions. Each action's purpose is
to collect information to provide it to a view.
I am confused.
Please, make it as simple as possible since I am newbie!
Thanks!
Controllers are just Ruby Class files which have a series of instance methods inside
Basic Explanation
Rails controllers are basically files where actions (methods) are kept
Each time you access a Rails app, you're sending a request to the system. The various technologies inside Rails route that request to a certain action, where your code can use the passed data to perform some sort of action (hence the name). The actions are kept inside controllers to give the application structure
So if you access http://yourapp.com/users/new, it tells Rails to load the new method in the users controller. You can have as many actions in the controllers as you want, but you have to tell the Rails routes system they are there, otherwise they won't be accessible
Proper Explanation
Rails Controllers are just Ruby Classes, storing a series of actions
The "actions" (instance methods) work on passed data (params) to create objects that can either be passed to the model, or used inside other methods
Whenever you send a request to Rails (access a URL), it first uses the ActionDispatch middleware to send your request to the correct Class (controller) instance method (action), and then your code does something with that data
Your job as a dev is to connect the right controllers with the right models, presenting the right data the user at the right time
DISCLAIMER: I don't write code in Rails (never did). I write Sinatra modular applications and use the MVC model.
You first need to clarify the MVC model. The MVC is an approach to programming web applications (in RoR) or user interfaces in general. So MVC stands for Model-View-Controller. I will try to explain a bit, but in order to understand this, you need to practice and play with it.
The Model: If you remove the layers of abstraction, it's your database scheme. The way your application interconnects in order to retrieve information.
The View: The way these informations are retrieved elaborated and served. Essentially is what you, or the client, see in the browser.
The Controller: The controller is what interacts with the program to produce a requested view or to alter a model. You request a view when you access a chart with statistical information, and you alter the model when you input DATA on it. In Rails ecosystem, ActionController is a class with a set of predefined methods to help you perform easier and quicker standard Controller actions like update a form, etc.
So the Action Controller allows you to alter data to your models (the db), or request a route to view your data, etc.
Action is not separated from controllers, it's basically what controllers do :-). Everything else is static.
If you feel that these concepts are still hard to grasp, try building a very basic modular application in Sinatra, and you will have a ground level view of how things work.
Explanation by Analogy (simple explanation without getting too technical)
I work in a busy office. I bark out orders (i.e. 'requests') to my staff to get em to do stuff.
e.g.
Sometimes I want a document so I can read it.
“Ngozi, pass me the ABC.ASX EOFY results please?”
Yes sir!
Sometimes I ask my staff to edit an existing document:
“Sunita, can you edit that report on the state of the union address?”
“Sure!” is the response.
I organise my staff based on the type of work they do
But I have a little problem.....I have 10,000s of different types of documents. Sometimes I want to get: (I) sports results and other times I want: (ii) the evening news, while still at other times I want: (iii) a collection of Donald Trump's latest 4 am Tweets.
So I created a new system. I have a staff member directly responsible for each type of thing.
Ngozi handles ASX (Australian Stock Exchange) Financial Results. And when I want Ngozi to do something (i.e. perform some type of action) then I tell him what to do.
Sunita works mainly on politics. Sometimes I”ll ask her to something (e.g. write up a report – this is one type of 'action', or I'll ask her to bring me a certain document – another type of action - and she'll do it. I like to get Sunita to work on politics and Ngozi to work on financial results. It's best to keep their responsibilities separated.).
And Freddie works on anything pertaining to Queen.
Etc. etc.
The meaning of the analogy?
In this case, the controller would be the person – who's responsible for handling certain types of requests. And the “action” would be the particular specific thing that I want done:
e.g.
getting a document or
edit something or even
creating a new document.
Hope that clears things up.
I am writing an ASP.MVC application and I know you can use authorisation filters on the cotrollers to control access to the pages but I am wondering what is the best approach to do if you want to control access to protected data within partial views.
From what I have read ASP.MVC doesnt offer this level of granularity.
This seems easily enough by adding the user permissions to the model as an attribute and then using a simple factory to decide if the view should be rendered or a blank view be returned.
So far I have
RenderPartial(PartialFactory.IsAllowedToRender("partialName", Model.Security), Model)
and the Factory either returns the view requested or a blank partial view.
Has anyone tried this before or knows why no one does this (apart from the extra effort)
We have done similarly with extension methods for HtmlHelper.
RenderPartialIfExists and so on. No shame in doing this if its something you are going to need frequently.
Doing it without the extensions as you have works as well, but its not as clean to read. Also, consider adding your security information to HttpContext.Current.Items, that way you don't have to pass it into the models all the time, and anything that needs to take advantage of it, helpers, controllers, etc have easy access to it, and you only have to fetch it at the beginning of a request.
I'm practicing my Rails development skills by building an app that will have different types of exercises for users. Most probably things like multiple choice questions for different subject matters.
One way to check to see if the questions are answered correctly is to use validations on the model. However, I don't really need to save the results, and it might end up in me creating a lot of different models, as each question will have its own validation to check each answer.
Is an alternative to create a new Controller action for each subject area? Is
How else might I organize this?
http://www.enode.com/x/markup/tutorial/mvc.html
With the MVC pattern, Controllers are usually in control of manipulating data kept by Models.
It's good form to keep most of your logic in your Controller. I'm not sure what you mean about a new Controller action, but what you'll probably want to do is set up some sort of form in your View, (see form_for) and fire that off to the Controller. The Controller does validations or whatever you need it to do.
This should be helpful:
http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html
So for example, you might have a form in your View (a quiz for example), calculate a user's score in the Controller, and save that as a field for a user in your database.
The debate on where to put logic is as old as the involved patterns themselves. For MVC, I decided to ask myself:
Is the logic involved essential for the model?
Would the model (in itself) function well without the logic?
Is the model free of any requirements towards the controller?
If I'd re-use the model, would I want to take the involved business logic along or would it be in the way?
My general advice: Put business logic as "low" (bottom: db, then model, then controller, then view) as possible without violating any of the following constraints:
Authentication and authorization does not belong to view. It's either a property of the controller (handle things like sessions and general api access rules, etc) or of the model (authorization: who may access which content?)
UI/display/input-method related things do not get into model or db. Don't let your model/db decide if and how to render html, xml or json.
Data consistency and integrity not in controller/view. Ideally, your data model only accepts valid data, uses transaction safety and reports back failure or success to the controller. Ideally, consistency is handled at db level.
A model shall be reusable with other controller/views in new project (think of switching to another web api). Too heavy constraints may render it unusable in new situations.
there might be more...
And generally: If in doubt, put in into the controller. ;)
Using Rails, I am building several sites which are very similar. I want to implement these as one Rails app answering to multiple domains, and change what is presented and the processing logic based on the domain name. The areas I need to change/skin per site are:
Views: The fields on a page differ slightly by site. Some sites have more/different fields than others, but there are some that are common across all
Models (which seems best to do this by defining a super class for the main model which varies and implement a subcalss for each site)
Controller logic. There is a lot of similarity but a few small processing differences, including which Model subclass to deal with
CSS (which seems fairly straight forward)
I have already implemented a mechanism which makes the current domain/app name visible to the views, controllers and models.
I was thinking of defining a view partial per site and using ERB logic to include the right one. The controllers seem like the least obvious part.
Any suggestions very much appreciated.
Cheers
Paul
I have implemented something similar for our application, HiringThing (http://www.hiringthing.com)
To do so, we use a before_filter on the application controller that parses request.host and determines what website the request is for. That then sets a variable #site that we reference in views, controllers and models to determine versioning requirements at runtime.
Suppose there is a call to get Analytics data from a third party or through our cache data on a server, for the "most popular items", and we show these items' names on all of our pages, should we put this code in Model, Controller, or View (Helper) component?
Maybe it is not strictly Model, because it is not directly in our data store.
Maybe it is Controller... should it be in the "general controller", such as in app/controller/application.rb to be sharable in all views? What if it is obtained in the controller code, but 1 month later, another person follow a new spec and remove the display of it on a view, then the code probably stay at the controller and nobody will remove it.
If it is in the helper... then what if in other part of the code, the controller need to get that data and store it in #popular? Also, aren't helpers suppose to help render data by putting repeated task in methods? So helpers shouldn't do so much data fetching logic.
Where is the code most properly placed?
Although I use .net mvc I think the same principles can apply.
So that being said here is what I usually have:
Controller > Service > Repository code.
So in this case you would have an Analytics service that handles the request and may make calls to third party or may call a repository layer (maybe both) that retrieves data from database. But this way all calls go through the same service. Plus removes any knowledge of how data is retrieved. In fact I had a similar situation one time where we were using a mail client and pulling in some of the analytics from their server and some from our database. All of that was hidden in the service layer so all that was returned was a model that could be used however it was seen fit.
Then all controllers who need it can share. In the view I would then have a helper that displays that data. Again anyone who wants can call the helper and pass the model data in required for that helper. This allows you to apply DRY principle.
Again this works for me. YMMV
I would like to suggest creating a google_api datasource. A quick google search should pop up a few of them that seem half finished to get a start with.
Use the GAPI class from google code from within the datasource to fetch data from google and format the results into something you can use.
Then you can setup a model for each metric you want to track. IE. class GoogleAnalyticsKeyword, GoogleAnalyticsAdWordCampaign etc. These models can be set to use your custom datasource. From the model you can do caching, validation etc on the data.
Then simply reference the models in the uses array in a controller. Either app_controller or dashboard_controller etc. Then just query the models from the controller you need the data to be available from.
http://code.google.com/p/gapi-google-analytics-php-interface/
http://github.com/msadouni/cakephp-plugin-google-analytics
(Disclaimer: this is coming from a Django background, my apologies if the terms or methodology don't directly translate into the MVC framework that you're using.)
My design process would basically go as follows:
I know that I wouldn't want to have to re-calculate the Analytics data for every page hit, so my choice is between just relying on a cache or using a cache in tandem with storing the temporary results in a database. I'd personally go for the latter method.
So I'd setup a Model to handle storing a subset of the Analytics data for the task at hand, saving the "most popular items" in your case. I would then create an automated task (say in cron, or in Django I would use Celery) to aggregate that data on a regular basis, perhaps at midnight every night.
Then I would just write some helpers to quickly query that aggregated data and display it in my template (the View in other frameworks).
In summary, I'd use a combination of the Model and View in the MVC paradigm. I don't see any reason to really involve the Controller in this process.
If you want to place it either Model, View or Controller, I would put it in a Model, because Models are responsible for CRUD actions, and retrieving a list of the most popular items is part of that.
I don't think it has to be in your data storage to count as a Model.
My 2 cents.