Ruby on Rails controller and architecture with cells - ruby-on-rails

I decided to try to use the cells plugin from rails:
http://cells.rubyforge.org/community.html
given that I'm new to Ruby and very used to thinking in terms of components. Since I'm developing the app piecemeal and then putting it together piece by piece, it makes sense to think in terms of components.
So, I've been able to get cells working properly inside a single view, which calls a partial. Now, what I would like to be able to do (however, maybe my instincts need to be redirected to be more "Rails-y"), is call a single cell controller and use the parameters to render one output vs. another.
Basically, if there were a controller like:
def index
params[:responsetype]
end
def processListResponse
end
def processSearchResponse
end
And I have two different controller methods that I want to respond to based on the params response type, where I have a single template on the front end and want the inner "component" to render differently depending on what type of request is made. That allows me to reuse the same front-end code.
I suppose I could do this with an ajax call instead and just have it rerender the component on the front end, but it would be nice to have the option to do it either way and to understand how to architect Rails a bit better in the process.
It seems like there should be a "render" option from within the cells framework to render to a certain controller or view, but it's not working like I expect and I don't know if I'm even in the ballpark.
Thanks!

How would the cell know in which controller it is rendered? This would break encapsulation.
You can use #render_cell in your controller view and maybe put some decider around it? Is that what you're asking for?

Related

Ruby on Rails routes to controllers

As I understand it, routes will take you from a starting point to a controller, and an action. The action brings up the associated views; so what if I don't need any views for my controller, and just want to just call a controller's underlying method, without rendering the view or route.
Lets say I have a FoodsController with several methods, and there exists methods cake, pizza, and chips within that controller. Each one queries the database for a secret message and stores it in a variable, but the request for this is going to come from some other part of our application.
To accomplish this am I supposed to use a route for this or some kind of dot syntax such as food.cake().
So I guess what I am trying to say is, hey "Server" go do this and come back to where you left off once its done.
Controller are only for URL endpoints. For example if you hit http://my.app/my_route, you need to map the my_route part to a controller action in your routes.rb file. But what happens if you type this into your browser? You'll want to see something right? So you need to return some data (json, html, erc). You can use render for this.
This is different to writing 'normal' Ruby code, i.e. Ruby outside a web framework. Do you understand what a class is and how the following works?
class MyClass
def initialize
end
def my_method
puts "my_method_called"
end
end
MyClass.new.my_method # => "my_method_called"
This is very basic Ruby and works in Rails as well, although there are some rules about where code needs to be written.
By the way, if you really want to make a controller action that renders nothing, just use:
render text: "", status: 204
return false
The status: 204 means "No Content".
You can use render json or text, if the method does not render anything, I think it should be private.
In your example you could use the cake method in another controller like so:
cake = Food.cake
Please note that this method should live in the food model and not the controller, since you do not need a view.

Ruby on Rails - Controller without Views

Iam new in Ruby on Rails. Normally I work with other web languages and now (of course) I try to compare it with other languages using on web.
But sometimes i have some problem to understand the philosophy and the character of Ruby on Rails. Of course i understand the concept of MVC.
But now Iam not absolutely sure:
Is ist OK to create and use a controller without views? In some cases you need a "class" for some usefull functionality used by other controllers they have views. Or is it a better style to use a module?
I try to find it out by reading a lot of articles and examples, but didnt find detailed information about this content.
When developing Ruby On Rails apps, it's recommended to put most of your business logic in the models, so for the controllers the logic need to be minimal to provide info for the views, so if it doesn't work with a view chance that you need a controller are really low.
Is it OK to create and use a controller without views
Yep it's okay.
The key thing to keep in mind is that Ruby/Rails is object orientated.
This means that every single you do with your controllers/models etc should have the "object" you're manipulating at its core.
With this in mind, it means you can have a controller without corresponding views, as sometimes, you just need to manipulate an object and return a simple response (for example with Ajax).
--
We often re-use views for different actions (does that count as not having a view):
#app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
def search
render :index, layout: false
end
end
The notion of skinny controller, fat model is sound in principle, you have to account for the times when you may need small pieces of functionality that can only be handled by a controller:
#app/controllers/users_controller.rb
class UsersController < ApplicationController
def update
#user = User.find params[:id]
#user.update
respond_to do |format|
format.js {render nothing: true}
format.html
end
end
end
A very rudimentary example of Rails is a drive-thru:
view = input interface
controller = accepts order & delivers
model = gets order packaged etc in backend
There are times when the controller may not need a view (for example, if you update your order with specific dietry requirements), and thus the notion that every controller action has to have a view is false.
It's really about making your controller versatile enough to manage your objects correctly.
Shared controller methods can be placed in ApplicationController. Also, in Rails 4 there are concerns (app/controllers/concerns/) where you can put the modules with methods that can be used by multiple controllers.
Controller handles request and renders corresponding view template. So controller without view is absolutely nonsense.
Every time request will execute this controller, it will just end with missing template error, so you will need to create view folder and put empty files with action name inside of it, which is obviously stupid.

Rails. How to put few controllers on one page

I am working on Todo app now and I have troubles. After sign in, I am on persons profile(first controller), on it I have button for new project(projects controller-2d controller) and after pressing it, appears button for new tasks(task controller-3d controller). How I can put all of this 3 controller's views on one page. Here an example of what I mean(approximately):http://todo.kzotov.ru/
You can put anything you want in the view. You could eager load the projects and tasks and put it all on the profile page. You also don't have to map controllers and views to models, so if the PersonsController or whatever is not what you're looking for, maybe do something more specific like ProfilesController and host all this functionality there.
MVC
You'll be best reading up on the MVC programming pattern -
The bottom line is that if you send a request to your application, it will only hit one controller#action. Your multiple "controllers" should not be something to consider - you should only look at the single controller action you're accessing at that specific time.
To be more specific about this, let me detail how it all works...
OOP
Ruby (on top of which Rails is a framework), is object orientated.
This is not just a fancy phrase - it's a real pattern of programming, which allows you to focus the flow of your application around the data / objects you want to create. The objects in Rails are derived from your Models - collating & organizing the respective data for your controllers
In order to understand how Rails works - you need to appreciate that everything you do is based on objects. Your routes, actions & data all work together to provide the end-user experience we know from Rails. How that happens is down to you.
Specifically, you want to look what what you're accessing
You don't want to load multiple controllers - you want to build several models and show those. This gives you the ability to show the HTML elements / files you want:
Recommendation
I would make sure you can put all your activity on your single view, which will then mean you have to determine your controller's data in order to provide you with the data you need to show:
#app/controllers/profiles_controller.rb
class ProfilesController < ApplicationController
def index
#your index
end
end
#app/views/profile/index.html.erb
<%= link_to "task", task_path %>
What you'll probably want to do is create a separate route / method to give them the ability to pull back ajax data when the initial button was clicked. I can detail this if you need it, but what I've given you should be ample food for thought

What's a good way to create subjective views in Rails?

I'm wondering what's the Rails Way™ to build a "subjective" view, that is, a view who's output is changed based on a provided param.
E.g., consider the following contrived case:
A user asks for a article in a blog app. In the request, she's sending the param time_zone=(-)1, to indicate that her timezone is -1. The app should then take that param, and in the output return the article and the time of the creation of that article - converted to her timezone.
The rationale for this server-side processing approach, is that it would be easy to change the client view, in particular if one's accessing the rails app through an exposed (mobile) api. (Mind you, it is no problem to handle the before-mentioned case with a client side script etc., but I'd like to avoid that.)
Somehow, I feel that this could easily belong to the model, had it not been for the fact that params isn't available there. I suppose that is for a reason. Controller is, from my point of view, definitely not the place to stick this.
The question is: should I stuff this logic in the view?
This logic would probably fit best in a subclass of your controllers. This subclass could define a filter method that sets appropriate instance variables, which you then reference in your view. I linked to a question that does exactly that for your timezone example (albeit without numeric timezone offsets, but the idea is the same). An alternate example might be say a different UI based on a URL parameter. In that case I might do something like this:
class ApplicationController
before_filter :set_ui
private
def set_ui
if params[:ui] == 'blah'
#ui = 'blah'
else
#ui = 'thing'
end
true
end
end
Then in your view you could have something like this:
<%= render :partial => #ui %>
Then any controllers that you create as subclasses of ApplicationController will have this functionality

What's the best way to do UJS in rails when you have a re-usable widget?

In my current project I have a couple instances where I have a re-usable form that exists inside a rails partial. This form submits to a specific controller via ajax (:remote => true). The controller does some stuff and then returns back the appropriate js.erb to modify the page via javascript.
This works fine for when I have a single view. But the problem seems to happen when this re-usable partial exists on multiple views. In view 1 I might want to issue a completely different set of javascript commands then in view 2.
As a concrete example, say I have a comments controller that has the normal CRUD operations.
I now have partial called _comments_box.erb. This _comments_box.erb contains the ability to submit a comment via a simple line:
- form_for comment, :url => post_comments_path(post), :remote => true do |f|
This submits to a comments_controller.rb create method which looks somethings like this:
def create
... do some stuff, like create a new comments model
respond_to do |format|
# will respond with create.js.erb
format.js
end
end
The create.js.erb in turn adds a comment to the view, perhaps doing a bunch of other updates to the DOM.
Say I render the _comments_box.erb within a view called post_summary.erb. Now I have another view, post_detail.erb that requires the same _comments_box.erb. However the post_detail.erb requires me to update completely different divs on the DOM in response to a new comment.
I need to create a different JS response for each instantiation. So I can either:
Create an alternate controller method, say create_2. Pass in some parameter to the _comments_box.erb from post_detail.erb to the _comments_box.erb partial so it knows which controller method to fire. This will allow me to have a separate file _create_2.js.erb that will allow me to manipulate the post_detail.erb view independently.
Forget about using js.erb altogether and just use plain old AJAX and get back JSON, and handle the javascript manipulation completely on the client-side.
It seems option 1 allows me to continue to use the UJS supported by Rails which is nice. But also means I probably will be adding a lot of duplicate code everywhere which is annoying. Is there a way for me to do this elegantly while continuing to use UJS?
That's exactly the purpose of Apotomo: http://apotomo.de/
Here is it's own description:
Apotomo is a true MVC widget framework
for Rails. Widgets are based on Cells
and provide reuseable view components.
Having bubbling events, they know when
and how to update themselves via AJAX!
Working with Apotomo widgets almost
feels like developing GUI components –
in a Rails environment.
Have a try, it's great.
I'd not recommend using UJS for frontend apps: server shouldn't take care of client side business. I agree it's useful and clean but it lacks performance and thus should be kept for backend stuff (RJS will move into a gem, see here: http://weblog.rubyonrails.org/2011/4/21/jquery-new-default).
That said, back to the solutions you expose:
1) I think you won't need an extra controller, you'd just have to pass additional params in order to know from where to query came from. A hidden_field could do the trick. With this info, render the good js.erb file
format.js { if condition
render "create.js.erb"
else
render "create_2.js.erb"
end
}
2) I'd go for it and return json but you'll face the same problem: knowing from where the request comes from.
A better solution (than using a hidden_field) might be to check the request.referer in your controller action. This way you leverage the fact that each context has a unique URL, and don't have to explicitly specify another unique value when rendering your widget partial.

Resources