When a new rails app is created, its ApplicationController contains a call to protect_from_forgery. But when creating a mountable engine, the namespaced ApplicationController does not contain that call by default. What's the reasoning for that?
Related
I am implementing rails app in which I have a rails engine as well.
In main app I have a model Marks
class Mark < ActiveRecord::Base
end
Rake routes for Mark is (simple and index page url)
mark_path(`)
Url for this /marks/
and inside the engine also there is a model Mark.
class Test::Mark < ActiveRecord::Base
end
For engine
marks_path
Url for Engine
/test/marks/1
Query
So how can access engine marks_path in engine's model.
Currently when use the url_helper in model it return main app routes instead of engine routes.
But I need engine routes.
I am learning rails using the teamtreehouse tutorial. The tutorial uses 3.1 but I am trying to learn 4.0, and as a result I have run into a difficulty presumably because rails 4 forces of the use of strong parameters. I have two models, a users model and a statuses model. I have used devise to create authentication for users, and have included new parameters. They are :first_name, :last_name, and :profile_name. I have created a relationship between users and statuses.
Currently the user sign-up with the new parameters is working; i can access them using for instance current_user.last_name. However, I want to show the profile_name of the user that created the post on the statuses index view(each user does not yet have a separate page). I want to do this using
status.user.profile_name
However it just shows up blank. If I do
status.user.email(which is a preconfigured devise parameter), it shows up no problem. I am guessing I have to whitelist these parameters in some controller but I don't know where or how.
Thanks
I think, here you will find your answer: https://github.com/plataformatec/devise/tree/rails4#strong-parameters
Based on above link, I think you should insert something like this in your ApplicationController:
class ApplicationController < ActionController::Base
before_filter :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:user) { |u| u.permit(:profile_name) }
end
end
And I already suggested in a previous question...
Strong parameters with Rails and Devise
...that you can create your own controller which could extend devise own controller. There is a gist for that:
https://gist.github.com/bluemont/e304e65e7e15d77d3cb9
A little bit more details in Devise doc: https://github.com/plataformatec/devise/tree/rails4#configuring-controllers
I am using scaffold on ruby on rails, and its great and all, makes everything simpler, but I dont understand one thing and the books or the web dont have a clear solution.
For exmaple, I use scaffold and I create table user and I can make /user/1 and I will see the user with the ID 1 , and if i make /user/edit/1 I will edit user with ID number 1, but on the controller the code its like this
def show
#user = User.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #user }
end
end
According the MVC Ive worked, the controller is the first in respond, so, in some way I should be able to indicate to use the show method, but how? I dont have anything else added on my routes file. any idea??
The default routes are "HTTP Verb: GET, Path: /photos/:id, Action: show, Used For: display a specific photo". See the documentation.
Scaffold add resource :users in your routes.rb file `. This actually enables all RESTfull routes. You can see the default routes in this table (bellow). This is what is defined as convention over configuration, and it is because of this that rails is magical. Once you master a few conventions, your will be able to do more with less.
table http://i.imm.io/150CI.png
By the way, this is a really nice site to use if you are planning to learn Rails. I'm not aware of a better source, even books.
I'm pretty new to Rails. I have been developing my app with RSpec. I have just followed a tutorial for Facebooker2 and added the before_filter for authentication.
#app/controller/application_controller.rb
before_filter :ensure_authenticated
However, my specs such as the one below failed because there's no valid session which is understandable.
#spec/controllers/answers_controller_spec.rb
describe "GET index" do
it "assigns all answers as #answers" do
get :index, {}, valid_session
assigns(:answers).should include(answers(:reading))
end
end
But I can't seem to find a way to fake a valid session for rspec to use in the following function.
#spec/controllers/answers_controller_spec.rb
def valid_session
{}
end
Is there a way at all? If not, what is the rails way of doing things for such a case?
If you aren't concerned about testing the actual authentication and just want to simulate a valid session, you could stub out the filter:
controller.stub(:ensure_authenticated).and_return(true)
EDIT: you may need ApplicationController.stub(...)
This is more for experimentation - I am aware that I can do this with --full but I wanted the functionality of namespacing in the app to avoid conflicts
The idea is to have a main app - which handles authentication, common items, admin screens etc
Then creating engines to add further functionality like
crm
cms
blog
wiki
forum
etc
These engines I can pick and choose as I need for whatever kind of app I am building.
Is this possible?
Is it just the case of applying both --mountable and --full options?
Experimenting - would there be any issue if I use the full option add rspec and then simple add
rails plugin new plugin_name --skip-test-unit --full --dummy-path=spec/dummy
and in lib\plugin_name\engine.rb
module PluginName
class Engine < Rails::Engine
# this is added by rails when an engine is mountable
# to isolate the plugin and prevent name clashes
isolate_namespace PluginName
# one of the additions to make rspec work from command line for the plugin
config.generators do |g|
g.test_framework :rspec, :view_specs => false
end
end
end
I have already created both --full and --mountable engines and have rspec finally working for anyone reading there are some great articles (see below), but wondered of the wider impact of doing this for the solution I am trying to create
I am still playing with this and will post my findings..
Any help/discussion will be massively appreciated.
Please Note
Why I want to do it - build once use many times...
I would never want a non-tech/client to add "plugins/engines" - this is purely to entertain point 1.
Issues I am Having...
Running the server on the top level app. Only when accessing content from the engine, (I can see by the error messages) I have a routing problem (root_path undefined or devise routes missing) - the parent application layout is being rendered, I can see it in the extracted source of the error. Progress but no cigar just yet!
Useful References
Engines vs Mountable Apps
3.1 engines with rspec
testing rails 3 engines
Listing Routes in a Mountable engine
I managed to get this working with the following steps:
In my parent app I was mounting the engine in routes.rb
mount PluginName::Engine => '/plugin_name'
I just removed it.
Created an application controller as Ryan Bigg below had stated.
class PluginName::ApplicationController < ApplicationController
...
end
As I wanted to have things name spaced when generating controllers, models, tests so you have to essentially comment out the isolate_namespace PluginName lib\plugin_name\engine.rb when I wanted the gem to be run in the parent app.
It is not yet an ideal solution. off the top off my head, I could use something like:
isolate_namespace PluginName if %w[development testing].include?(Rails.env)
but will have to test if this is practical.
Kudos to Ryan for helping me find my way many thanks
Furthermore, the same can be done with the --mountable switch version and all you need to do is one further step in your engines config/routes.rb replace
PluginName::Engine.routes.draw do
with
Rails.application.routes.draw do
Yes, you can reference the parent application assets just by referencing them in your application like normal:
<%= stylesheet_link_tag "application %>
Although, not sure why you would want to do that because...
I'm going to answer your first question with the answer to your second question.
To use the application's layout you will need to modify the ApplicationController in the engine (which is namespaced) and have it inherit from ApplicationController in the engine.
That will then have the controllers for the engine using the layout provided by the engine. I'm doing this in my engine, forem.
One day, this will be covered in the Engines Guide that, at this time of writing, is currently being written.