Creating Controllers / Views for a Rails 4 Engine in App - ruby-on-rails-4

Using Rails 4 I have an engine called Core that contains business rules and data objects for a system we're using. This is designed to be lean and in included in a few different apps.
I am creating an app that will contain some special CRUD screens for some of this core data, and I am not sure the best way to set up routing.
In other words, I want to create views and controllers for an engine's models without mounting the engine in my routes.
However, after running rails g scaffold_controller core::rep, I can't seem to get the url helper methods loaded. In my config/routes.rb:
namespace :core do
resources :reps
end
rake routes returns:
Prefix Verb URI Pattern Controller#Action
core_reps GET /core/reps(.:format) core/reps#index
POST /core/reps(.:format) core/reps#create
new_core_rep GET /core/reps/new(.:format) core/reps#new
edit_core_rep GET /core/reps/:id/edit(.:format) core/reps#edit
core_rep GET /core/reps/:id(.:format) core/reps#show
PATCH /core/reps/:id(.:format) core/reps#update
PUT /core/reps/:id(.:format) core/reps#update
DELETE /core/reps/:id(.:format) core/reps#destroy
Which seems fine.
However, upon navigating to URL: /core/reps
Showing /app/views/core/reps/index.html.erb where line #14 raised:
undefined method `edit_core_rep_path' for #<#<Class:0x00000002adf578>:0x00000002adc3a0>
Which I take to mean that the url_helpers aren't being correctly set up, and I have a growing suspicion that I am approaching this problem in the wrong way.
Is there something I am missing? Should I be trying to extend Engine Controllers in the app?
Can I use an Application's helpers with an Engine's models? Or do I have to mount the engine?
I know I can rails g scaffold_controller rep and then just patch the controller to load the data from the engine, but that doesn't seem quite right.

Have you looked at the proxy helpers bit in http://guides.rubyonrails.org/v4.1.8/engines.html#routes ?

Related

Running rails app both as engine and app

I'm transforming a Rails application (say appA) into engine so that I can hook it into another Rails app (say appB). However appA must run as a Rails app solely as well. That's because a customer can buy
appA or
appB with appA. There is no option of buying only appB.
Following rails oficial guide I made (among others) following changes:
Changed Rails.application.routes.draw to ActionPlan::Engine.routes.draw in routes.rb.
Created lib/action_plan/engine.rb with content shown below:
module ActionPlan
class Engine < ::Rails::Engine
isolate_namespace ActionPlan
end
end
Now when I run rails s I get /action_plan/config/routes.rb:1:in '<top (required)>': uninitialized constant ActionPlan::Engine (NameError).
I guess I should initialize ActionPlan::Engine in application.rb file somehow but I don't know how neither whether it's the way to go.
So is it possible to build an app/engine in rails such as appA? If it is, how can I overcome that problem?
After some researching and talking to some friends, I found out that it's not possible to do such a think with rails, but it's possible you to create another rails app (say appC) and use it only to run your engine, i.e appC is a silly rails app used only to make it possible to run your engine.

How to use react build websites without using react-router ?

I'm building a website with Django and react, and since Django itself has a routing system, and I don't want to discard that, so I decide not to use javascript routing libraries.
I'm using webpack to bundle my files, but since I'm not using react router, there's a lot of webpack entry files, and a lot of bundled files (almost one per page), and I'm not sure if this is a 'correct' way.
And since there's one javascript file per page, the states or other things between different pages are not shared, every page is independent of each other. Can I have some 'shared' things without using react-router?
I know Facebook itself and Airbnb don't use react-router either, so how do they use react? How do they handle a lot of bundled files?
Can anyone work for a company that does not use react-router share your company's solutions?
The proper way to accomplish this is in the same way as you do it using vanilla javascript or some library like jQuery.
You don't manage a state in the front end, you grab the state server side and you put it in the HTML and then you use it with javascript.
React.js isn't different and if you're using redux you could put that data directly in the initial state of every page/section of your whole webpage.
<>
Yes. But in order to share in the way you imagine, you do have to make your app single paged. That is, you don't link around to different URL's. Any view change would change at most the #anchor part of the URL, but needn't do anything to the URL - just use Javascript logic to change what component(s) get rendered. As long as the base part of your URL stays on the same page, your shared objects will stick around.

What happens in a simple Django Rest Framework application that has an Angular front end?

I've been learning Django for some time now, and I found this image helpful:
I'm now delving into Angular JS, and I'm trying to figure out how each of the components (Directives, Controllers and Services ?) interacts and if there is a similar 'cycle'. This blog looks like it comes close to answering my question.
But how is the picture different if we have a Django-Rest-Framework end point providing the books in the above example?
Do we want URL resolution from Django, or Angular? Or more answerabley, which takes precedent?
What is the general order that things happen in when we go to say localhost:8000/books ?
Does urls.py catch this?
urls(r'^books',angular_redirect)
If so what does that function (angular_redirect) need to render to get angular to respond?
Does angular routing catch this?
$routeProvider.when('/books', {templateUrl: 'partials/book_partial.html', controller: 'MyBookCtrl'});
So does this mean my controller then registers a service hooked up to say localhost:8000:/book_list.json and does that need to be registered in the urls.py?
How does Angular know where to get the DRF JSON, if we're wholly relying on angular for routing. I've seen this package that lets you use the django models in the angular JS, but I'm not certain if that makes the picture more or less complicated.
Apologies if this is overly broad, I'm very new and trying to get my head round some of the general concepts of these technologies. Any advice on narrowing this question so it's answerable would be appreciated.
Your question has a simple answer: Angular handles the front end and Django (and DRF) handles the back end, and that includes URLs. Users on a fully Angular-powered site should never directly hit a URL that is served by Django, except possibly for the initial page that serves the page structure and JS itself.
Apart from that, the only interaction between the two is when Angular specifically requests JSON from Django, via an Ajax call. That may well be in relation to a navigation event by the user, but just as equally could be triggered on a timed basis or via some kind of websocket functionality.

Accessing images on production, from javascript, in Rails 4

It appears that now in Rails 4 using asset pipeline and the sprocket-rails gem, when images are processed, their filename is appended with an md5 fingerprint like css and javascript. While this makes sense because md5 fingerprints are awesome, it makes it increasingly difficult to access that image from javascript. In rails 3.2, I could access the image with /assets/image_name.jpg and it would serve properly, but in rails 4 that asset doesn't exist, it only exists with the md5 fingerprint in the name.
I know that rails provides helpers to access the image via erb <%= asset-url("image_name.jpg") %> but that is less ideal in javascript, because I am not using erb in my js. There are plenty of ways I could hack this with data-attributes serving in the views or using a script tag in my view and setting some globals, but I am looking for a nice solution to this problem, if it exists.
Any help is appreciated, thanks.
Another option to consider (although I wouldn't recommend it) is to use a custom route in your application controller to grab the asset path for you in the controller and either return the url to the asset with the md5 hash or possibly just render the raw binary data of the asset (although this will add processing overhead to your application).
For example, you make a AJAX get request to
http://yourapp.com/images?file=my_image.jpg
Then in your controller your action method would look like this:
def images
ActionController::Base.helpers.asset_url(params[:file])
end
This would then return the url path to the asset. The downside to this method is that it requires that you make two requests on the JS side. The first to get the path to the asset and the second to actually load that asset with the returned path.
To reduce this down to one request you could have the application read the image from the file system and return the proper headers so the browser thinks it is an image being returned and therefor will render the url provided. However, this would be a lot more work for the application and a lot more unneeded disk IO on your server.
It may take two requests for each image on the client to achieve what you want but you have to sacrifice somewhere...
Why do you need to use the asset pipeline for images? I get the hashing behavior. But normally the assets would be preprocessed. If you put the images in the public hierarchy as in olden times, you would get normal path routing.
Here's a quote from the Asset Pipleline guide that I think might be germane.
"Assets can still be placed in the public hierarchy. Any assets under public will be served as static files by the application or web server. You should use app/assets for files that must undergo some pre-processing before they are served."
Unfortunately, I think that you are stuck either adding an ERB extension to your JS and using the asset helpers, or else not using the asset pipeline for the assets.
When you say "I am not using erb in my js", do you mean you don't want to, or simply that you aren't? Because you can!
If you rename the relevant JS files with the extension .js.erb then you can use the asset_url helper in these files like so:
var src = "<%= asset_url('photo.jpg') %>";

Django, REST and Angular Routes

I'm trying to wrap my head around combining a client-side framework like AngularJS with Django. One thing that's really confusing me is the issue of routes and REST.
I've been trying to read a lot about it online, but documentation is limited, especially in terms of Django being combined with Angular (little snippets here or there). I understand that I need to add a REST framework like TastyPie to make a robust REST interface in my app in order for Angular to plug in and grab resources.
However, I'm confused as to how to properly map out my routes in such a way that (1) my server-side app can render my single-page app (SPA) with angular plugged in (2) routes that are supposed to load information/render templates (angular) and retrieve data from the server (django) don't conflict. Like if I have someone going on my website and doing site.com/user/1234 - that route is associated with both the Angular route and the Django route - except one renders a template and the other spits out JSON based on what is retrieved from the DB/server.
In addition, by using the REST api, do I forego a lot of the advantages I have in terms of having ModelForms being synchronized with my Models, etc? Is there any way to maintain this with AngularJS or do I have to look towards an AngularJS substitute.
The question isn't really specific to Django - just a matter of understanding the relationship between back-end and front-end in an SPA.
Routes are not duplicated between the back-end and the front-end. Your Django routes should be set up like:
/api/foo
/api/bar
...
and one single route that delivers a single page full of HTML partials, e.g.
/
The rest of the routes will be defined in Angular, e.g.
/articles/234
/blog/date/slug
...
The Angular controllers that handle those public-facing routes will in turn make $http calls against the API URLs and each will deliver one Angular partial. So there is no duplication, no overlap.
To the second part of your question, you can still use the Django ORM model relationships when constructing your API data, but yes, you'll lose all of that Django goodness when building the front-end.
If you build your API right, all of the data you need in each view will be fully present in the JSON feed that Angular consumes in that view. So you're using the ORM for back-end data construction, but you can't just decide to traverse a model relationship in a template without first preparing the back-end data to provide data for it.
Yes, it's a very different way of thinking of things, and yes it's quite a bit more complex than doing straight Django (or Rails). That's the cost of building a web app rather than a web site.