I am using the Socialization Gem for "Liking" and "Following" objects. I am doing this via AJAX. Right now, the only likeable thing I have is a Program.
I was able to get it working with both a Likes controller with create and destroy actions, as well as a custom controller action (like) in the Programs controller.
I can post the code if needed, but I was just curious if one of these is the better method, or if both are acceptable and it just depends on my needs. (The custom method programs#like is less code, but it seems less Rails-y.)
Related
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.
I have a logic question and I cannot figure out how to do it. First of all, I am working on an social networking site, and I completed the site in pure PHP, but now I am re-writing the backend in rails.
My questions is, I generated UsersController, it has new, create, show, edit, update, delete, and destroy.
I thought I could use "new" to display sign up page, "create" to process sign up, "show" to display profile page, "edit" to display account settings and "update" to process edit.
I might have a logic problem here, maybe I should put "new" and "create" in a signup controller. This where I get confused. The problem with the first logic I said, I have 2 layouts, one of them is for before login, and the other one is for after login. (You can imagine Facebook's header before login, and after login).
So, when I have 2 different layout, I cannot use 1 controller in 2 layout. Because sign up page has "before login header design" and account settings and profile has "after login header design". And as you can guess I define layout in controller.
I don't know if I explained well. Thank you.
By default, Rails will look-up a layout with the same name as the controller, or else application.html.erb. But you can also specify one controller-wide (which won't help you, but bear with me)
class SomethingController
layout "some_name"
...
That's still layout-wide, so not what you need.
But you can also specify a specific layout on each call to render in an action:
def edit
#some logic
render "some_template", :layout => "some_layout"
end
Or, to take the default template lookup, but still specify a layout:
def edit
# some logic
render :layout => "some_layout"
end
There's another way you can specify layouts too, which might be especially appropriate for the use case of "one layout if not logged in, another if logged in":
class SomeController
layout :method_name_to_determine_layout
# ... actions ...
protected
def method_name_to_determine_layout
if current_user
"logged_in_layout_name"
else
"not_logged_in_layout_name"
end
end
You can learn more about the different ways to specify layouts in the Layouts and Rendering Rails Guide
Hope this helps.
Rails has basic CRUD default actions. Additionally each action can have different processing depending on the HTTP verb. You can also add custom actions & routes.
It is best to follow standard Rails practices for each default action. For example, "new" action should route to the form to create a new user when accessed via GET. An HTTP POST to the form should route to the "create" action.
If you need to add an additional controller action, do so with a custom method. Again, I stress, simple CRUD actions should follow normal Rails conventions.
Read more about routing
Read this guide many times to understand simple CRUD actions in Rails
Instead of using 1 controller in 2 layouts, I decided to use separate controllers. So, I have profile_controller, which has "edit" and "update" for account settings and "show" to display profile. And I also users_controller, which has followings: login, login_attempt, signup, signup_attempt, etc..
So, I am not putting signup and edit together in 1 controller, instead using 2 different controllers is much better and clean, I guess.
Sounds like you're trying to roll your own authentication.
I'd recommend using Devise... great tutorial here:
The reason for this is two-fold.
Firstly, Devise gives you the ability to split your app between authenticated and non-authenticated users. Namely, it provides the user_signed_in?, devise_controller? and current_user helpers to aid with this.
This might not appear like a big deal, but it will actually help you with your layouts (I'll describe more in a second).
Secondly, Devise is pre-rolled. Your questions about how to handle signups and registrations have already been solved. Of course, there's nothing preventing you from making your own authentication (Devise is just built on Warden after all), but it should give you some ideas on how this has been done already.
In regards your original question (about layouts), the other answer is very good (in terms of setting layouts per method etc).
To add to it, I would say that you have to remember that Rails is a series of classes. As such, setting the layout option in the controller is the best way to ensure you're getting the correct one.
Here's Rails explanation on it:
#app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
layout :your_layout
private
def your_layout
devise_controller? || !user_signed_in? ? "new_user" : "application"
end
end
I've found it better to keep your logic as terse as possible. IE only have one set of logic for the layout. We tend to keep it in the ApplicationController, overriding where necessary.
--
Finally, your questions also highlighted a base misunderstanding of Rails. I'm not being disrespectful; I've found the clearer your perception of the framework, the better you can work with it:
You have to remember several key points with Rails:
It's an MVC (Model View Controller) framework
It's built on Ruby; hence is object orientated
maybe I should put "new" and "create" in a signup controller. This where I get confused.
If you take Devise as a model, you'll see that you could treat your controllers as layers of abstraction for objects. That is, as Devise shows us, you can have sessions and registrations controllers.
I'm not advocating you do this exactly, I am trying to show that if you put the focus onto the objects you're working with, it becomes clearer where your controller actions should be placed.
You'll also be best understanding the CRUD (Create Read Update Destroy) nature of Rails controllers & objects. The standard Rails controller is set up as such:
Whilst this is not strict, it does give you another indication as to the structure your controllers should adhere to.
You may know this stuff already!
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
i am new to RoR and I am a little confused on this topic. Is the scope of variables in the controller only accessible in it's corresponding view?
for instance say I generated a Post scaffold (with blog_text and title). I also generated a controller called static with a home page view/controller resource. Is there any way I can access/print all of the posts from within my home page view? would i have to do something in my static#home function? I cant jsut do Post.all correct?
The controllers are tied to their corresponding views. But you need to use an instance variable (a variable with '#' in the front e.g. #variable) if you want to be able to use the variable in your views. Also, it doesn't matter what model/view/controller you're in when you request data from your db. So in response to your question, yes you can just do something like
#posts = Post.all
in any controller and then access the posts in your views. This is pretty basic stuff, you should study the guide a bit more.
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?