First of all: Yes, monkey patching is bad, I'm feeling like a sinner already. But in this case I haven't found another solution.
Situation:
Engine 1 (Alchemy-CMS): Provides a page model that contains several elements.
Engine 2 (my Alchemy-Contentable): Should provide a way to bind these elements to any resource (=model) you like.
Purpose is to give the resource cms-capabilities like Alchemy has, that means adding elements like headings, paragraphs, pictures, videos...
On the "page-layer" everything is fine. I created a mixin for a model that identifies itself as contentable towards the element.
I want to stay as close as possible to alchemy and therefore inheriting from element is not an option (new database-table, new associated models...).
So monkey patching seems adequate here (still hacky, but I'm fine with it this time I guess).
Problem:
How do I successfully monkey-patch one engine's classes from another engine?
When I try to reopen classes as usual it complains not to find the constant. Probably this is due to lazy loading of classes.
What works is:
config.after_initialize do
Alchemy::Admin::ElementsController.send(:include, AlchemyContentable::ElementsControllerMixin)
Alchemy::Admin::ElementsController.send(:before_filter, :load_contentable_to_page, :only => [:index, :new, :create])
end
but this seems to be error prone, especially when accessing a newly defined message from a mixin (like Alchemy::Element.my_new_method in model_mixin, which is included in your app's model)
Has someone had a situation like this before? Any ways out? At least a 'reliable' way to create and overwrite some methods in the engine's classes and to call them inside a mixin?
A solution is to monkey-patch the Alchemy::Page model in the following fashion:
require File.expand_path('../../app/models/alchemy/page', Alchemy::Engine.called_from)
module Alchemy
class Page < BaseRecord
# Your code goes here...
end
end
Note the require statement which will ensure that the original class is extended and not overwritten by your file.
See this blog post for more context.
Related
I've noticed a few places in the Rails source code where module_eval is used. One place is in ActiveRecord::Enum and another is in ActiveRecord::Store. I'm familiar with class_eval and instance_eval and have used them for extending the functionality of existing classes or objects, but in the case of module_eval, it seems like it's serving a different purpose.
In both cases they are using a similar pattern to define the module:
def _store_accessors_module
#_store_accessors_module ||= begin
mod = Module.new
include mod
mod
end
end
If the module is being included in the class it's defined in, what benefit is there to defining related methods in a nested module like this? Is it better isolation of code? The reason I'm asking is because I have a gem that adds functionality to Active Record, and am wondering if this approach is more of a "best practices" way of doing the same thing. Here's the relevant source code of my gem for reference.
The reason the methods are being defined in a nested module is so that users may override the methods and still have access to super to get at the original functionality. Recall that when you include modules in Ruby they are inserted into the ancestors list for the current class and super works by simply iterating through the ancestors array, looking for the first object that responds to the current method. To this end, the name of the module is not important as it is simply an inheritance-chain-like delivery mechanism. So that's why they define just an anonymous new module and include it on the fly.
If you look at the blame view for the 2 examples you listed, you can see the reasoning behind the changes. The commit message in the ActiveRecord::Store example makes the case pretty well. As you can see, they're adding the ability to override the accessor definition color and tack on to the results of the original method via super || 'red'. Whereas, in the original implementation, one would have to both override the color accessor method and then do the same work as the original accessor method, i.e. call read_store_attribute(:settings, :color) || 'red'. So it's all about not being forced to reproduce the internals or using alias method chains to augment the functionality of the dynamically defined methods.
I'm not sure whether this is a useful feature in your gem, but I'm guessing maybe not as your accessors seem to be returning well-defined object enum-related objects. But, of course, that's up to you and the gem's users :).
I have an application in Ruby on Rails with mvc framework. As of now, I have API calls in the controller but don't think this is the right place for them. What kind of file should all my API calls go in? Thanks
def getDetails(id)
api_response = HTTParty.get(base_uri, :query => {:DID => id, :DeveloperKey => devKey})
#json_hash = api_response.parsed_response
return #json_hash
end
API calls to external services (3rd party) are not specific to your app, as their service is available to everyone (in theory). It is my understanding that these sorts of features go in the lib/ directory because they are not app specific. Ideally you could then pull out the code from your lib in your project, and drop it into someone else's lib/ in another project and it would still work just fine.
Put the call in the lib/. If you want, you can create the a model from the returned data in your controller.
It would look something like this:
app/controller/
class YourController < ApplicationController
def getDetails
# keep in mind, api call may fail so you may want surround this with a begin/rescue
api_response = YourApiCall.new.get_details(params[:id])
# perhaps create a model
#model = SomeModel.new(fname: api_response[:first_name], lname: api_response[:last_name])
# etc...
end
end
lib/
require 'HTTParty'
Class YourApiCall
def get_details(id)
HTTParty.get(base_uri, :query => {:DID => id, :DeveloperKey => devKey})
#json_hash = api_response.parsed_response
return #json_hash
end
end
Very late to this one, but thought I'd add my 2p/2c.
I like to try to keep my controllers clean of anything apart from controller code, which I loosely define as program flow code based on request type and parameters. For example, choosing the correct template for the request type or choosing the correct method to call based on whether a user is logged in or not.
When it comes to calculating the responses, I don't like to litter the controller with lots of code that manipulates models and sets instance parameters. This is hard to test and even harder to re-use. I prefer to defer to another object and return a single value object to the template.
Sometimes I can defer to a model: maybe it's a simple look-up and I'm just sending a single model to the template, or an array of models.
Maybe I've implemented a useful method in a model to return an appropriate value or value object.
However sometimes I'm doing something that doesn't use a model, or that uses a several models, or that doesn't feel like it should actually be cluttering up the model. In this case, neither the controller nor a model is an appropriate place for the code.
The lib directory doesn't feel right either. I tend to treat the lib directory as somewhere that contains code that I haven't been bothered to turn into gems yet. If the code I'm writing only makes sense in the context of the application, it doesn't sit well.
So I turn to service objects. Under the 'app' folder I have a 'services' folder, which contains small, functional classes that encapsulate single chunks of site behaviour. (Or sometimes, coordinate several other services to provide a simple interface for the controller.)
This allows me to slim down my controllers AND my models, and makes a perfect place to put code that needs to contact an API.
If you wanted to go one step further you could wrap the API itself in a wrapper class (or set of classes) and keep those in the lib directory (for conversion to a gem at a later date perhaps). Then the service object would perform the task of calling the API wrapper with the appropriate values (passed from the controller) and responding with something that a template can interrogate cleanly.
Of course, you can go further than this and add more layers. A presentation layer, for example, could sit between the service object (providing generic values) and format data for a specific view. (Maybe you want to provide both a web page and an RSS feed and they need different date formats for example.)
But you get the idea.
By my coding style (and understanding of MVC), external calls would be placed in a "tableless" model. RailsCasts 193 talks a bit about this concept, and a less clunky syntax is supported in Rails 4. If you need to have any manipulation of the code, the model seems like the logical place to place these. Moving those methods into the controller would work, but could create problems as your app grows.
Another consideration with external API calls is actually storing those in a database, which would should definitely be in a model at that point, so (to me) it becomes clearer that these really should be in the model.
In the Rails application I’m currently developing I have many “request” models. We are using a lot of web services and we have a lot of different requests to those services, each of them with their own logic (mostly validations). So they are all grouped in a module as a namespace:
module Request
end
So now every request is something like:
class Request::SendSomeData
end
So far, so good… The thing is that we are going to have a lot of such requests which will share some common logic. It is easy to include the module
class Request::SendSomeData
include Request
end
… (so it will act both as a namespace and a mixin), but I was wondering if there is a way to make it without the include (as it is going to be some kind of code repetition).
Is there a way for Ruby to put some instance methods to all the classes in a module’s namespace without explicitly including the module?
In other words can I have something like:
module Request
def someMethod
end
end
and
class Request::SendSomeData
end
and be able to use
Request::SendSomeData.new.someMethod
at the same time?
What you are asking can't be done without some evil hackery.
You either have too many classes, or are focusing on an issue that is too unimportant. It's only one line of code per class.
An alternative is to create a base model class, as I have previously described in another question, but this requires the derived classes to each call set_table_name, so it won't save you any typing.
Today, trying to DRY up some code, I extracted some duplicate File.exists? code used by several helper methods into a private method
def template_exists?(*template) and accidently monkey patched this already existing Rails helper method. This was a pretty clear indicator of a code smell, I didn't need need any the inherited methods, yet I inherit them. Besides, what was my refactored method doing in this helper at all?
So, this helper does way too much and hence violates SRP (Single Responsibility Principle). I feel that rails helpers are inherently difficult to keep within SRP. The helper I'm looking at is a superclass helper of other helpers, counting 300+ lines itself. It is part of a very complex form using javascript to master the interaction flow. The methods in the fat helper are short and neat, so it's not that awful, but without a doubt, it needs separation of concerns.
How should I go forth?
Separate the methods into many helpers?
Extracting the code inside the helpers methods into classes and delegate to them? Would you scope these classes (i.e. Mydomain::TemplateFinder)?
Separate the logic into modules and list them as includes at the top?
other approaches?
As I see, no 2 is safer wrt accidential monkeypatching. Maybe a combination?
Code examples and strong opinions appreciated!
Extracting helpers methods into classes (solution n°2)
ok to address this specific way to clean up helpers 1st I dug up this old railscast :
http://railscasts.com/episodes/101-refactoring-out-helper-object
At the time it inspired me to create a little tabbing system (working in one of my apps in conjunction with a state machine) :
module WorkflowHelper
# takes the block
def workflow_for(model, opts={}, &block)
yield Workflow.new(model, opts[:match], self)
return false
end
class Workflow
def initialize(model, current_url, view)
#view = view
#current_url = current_url
#model = model
#links = []
end
def link_to(text, url, opts = {})
#links << url
url = #model.new_record? ? "" : #view.url_for(url)
#view.raw "<li class='#{active_class(url)}'>#{#view.link_to(text, url)}</li>"
end
private
def active_class(url)
'active' if #current_url.gsub(/(edit|new)/, "") == url.gsub(/(edit|new)/, "") ||
( #model.new_record? && #links.size == 1 )
end
end #class Workflow
end
And my views go like this :
-workflow_for #order, :match => request.path do |w|
= w.link_to "✎ Create/Edit an Order", [:edit, :admin, #order]
= w.link_to "√ Decide for Approval/Price", [:approve, :admin, #order]
= w.link_to "✉ Notify User of Approval/Price", [:email, :admin, #order]
= w.link_to "€ Create/Edit Order's Invoice", [:edit, :admin, #order, :invoice]
As you see it's a nice way to encapsulate the logic in a class and have only one method in the helper/view space
You mean seperate large helpers into smaller helpers? Why not. I don't know your code too well, but you might want to consider outsourcing large code chunks into ./lib.
No. ;-) This sounds awfully complex.
Sounds complex too. Same suggestion as in 1.: ./lib. The modules in there are auto-loaded if you access them.
No
My suggestion is: Hesitate from using too many custom structures. If you have large helpers, ok, might be the case. Though I wonder if there is an explanation why that whole helper code is not in the Controller. I use helpers for small and simple methods that are used inside the template. Complex (Ruby-)logic should be put into the Controller. And if you really have such a complex Javascript app, why don't you write this complex stuff in Javascript? If it really has to be called from the template, this is the way to go. And probably makes you website a bit more dynamic and flexible.
Regarding monkey patching and namespace collisions: If you have class name, method names etc. that sound common, check out if they are defined. Google, grep or rails console for them.
Make sure you understand which code belongs to
Controller: Fill variables with stuff, perform user actions (basically the computation behind your page)
Helper: Help doing simple stuff like creating a fancy hyperlink
def my_awesome_hyperlink url, text
"Fancy Link to #{text}"
end
./lib: More complex stuff that is used by more than one Controller and/or also used directly by other components like Cucumber step definitions
inside the Template as Ruby Code: Super easy to read
inside the Template (or ./public) as Javascript code: Matter of taste. But the more dynamic your app, the more likely code belongs in here.
Ok this is a really hard question to answer. Rails kind of leads you down the path of view helpers and really doesn't give you a decent baked-in alternative when you out-grow it.
The fact that helpers are just modules that are included in to the view object doesn't really help with the separation of concerns and coupling. You need to find a way to take that logic out of modules altogether, and find it a home in its own class.
I'd start by reading up on the Presenter pattern, and try to think of how you might be able to apply it as a middle layer between the view and the model. Simplify the view as much as possible, and move the logic to the presenter or the model. Move javascript right out of the view, and instead write unobtrusive javascript in .js files that enhance the functionality of the existing javascript. It definitely does not need to be in the view, and you'll find that helps clean up a lot if stuffing js in your views is what got you in this mess.
Here's some links for reading:
http://blog.jayfields.com/2007/03/rails-presenter-pattern.html
About presenter pattern in rails. is a better way to do it?
http://blog.jayfields.com/2007/01/another-rails-presenter-example.html
http://blog.jayfields.com/2007/09/railsconf-europe-07-presenter-links.html
Don't get too caught up in the specific code examples, rather try to understand what the pattern is trying to accomplish and think how you could apply it to your specific problem. (though I really like the example in the 2nd link above; the stack overflow one).
Does that help?
It is difficult to suggest a clear solution without the code. However since helper methods all live in the same global view instance, name collision is a common problem.
#Slawosz may be a solution but no really fit for the helpers philosophy.
Personally I would suggest to use the cells gem : cells are like component for rails, except lightweight, fast, cacheable and testable.
Also to answer your specific problem they're completely isolated. When your view helpers get to complex they're definitely the solution.
(disclosure I am not the creator of this gem, just happily using it....)
# some view
= render_cell :cart, :display, :user => #current_user
# cells/cart_cell.rb
# DO whatever you like in here
class CartCell < Cell::Rails
include SomeGenericHelper
def display(args)
user = args[:user]
#items = user.items_in_cart
render # renders display.html.haml
end
end
Also you can use a generic helper for dryness here without fearing name clash.
I would create a small library which is responsible to manipulate yours forms.Some well named classes, some inheritance, and as input you pass ie parameters, and as output you can has ie. objects for partials used in this form. Everything will be encapsulated, and it will be easy to test.
Look at AbstractController code, and then Metal to see how smart are rails designed, maybe there You will find inspiration how to solve your problem.
Your approach is correct but I would prefer 3rd point i.e. separate the logic into modules.
Modules open up lots of possibilities, particularly for sharing code among more than one class, because any number of classes can mix in the same module.
The greatest strength of modules is that they help you with program design and flexibility.
Using such kind of approach you can achieve design patterns.
I'm really enjoying Rails (even though I'm generally RESTless), and I enjoy Ruby being very OO. Still, the tendency to make huge ActiveRecord subclasses and huge controllers is quite natural (even if you do use a controller per resource). If you were to create deeper object worlds, where would you put the classes (and modules, I suppose)? I'm asking about views (in the Helpers themselves?), controllers and models.
Lib is okay, and I've found some solutions to get it to reload in a dev environment, but I'd like to know if there's a better way to do this stuff. I'm really just concerned about classes growing too large. Also, what about Engines and how do they fit in?
Because Rails provides structure in terms of MVC, it's natural to end up using only the model, view, and controller containers that are provided for you. The typical idiom for beginners (and even some intermediate programmers) is to cram all logic in the app into the model (database class), controller, or view.
At some point, someone points out the "fat-model, skinny-controller" paradigm, and intermediate developers hastily excise everything from their controllers and throw it into the model, which starts to become a new trash can for application logic.
Skinny controllers are, in fact, a good idea, but the corollary--putting everything in the model, isn't really the best plan.
In Ruby, you have a couple of good options for making things more modular. A fairly popular answer is to just use modules (usually stashed in lib) that hold groups of methods, and then include the modules into the appropriate classes. This helps in cases where you have categories of functionality that you wish to reuse in multiple classes, but where the functionality is still notionally attached to the classes.
Remember, when you include a module into a class, the methods become instance methods of the class, so you still end up with a class containing a ton of methods, they're just organized nicely into multiple files.
This solution can work well in some cases--in other cases, you're going to want to think about using classes in your code that are not models, views or controllers.
A good way to think about it is the "single responsibility principle," which says that a class should be responsible for a single (or small number) of things. Your models are responsible for persisting data from your application to the database. Your controllers are responsible for receiving a request and returning a viable response.
If you have concepts that don't fit neatly into those boxes (persistence, request/response management), you probably want to think about how you would model the idea in question. You can store non-model classes in app/classes, or anywhere else, and add that directory to your load path by doing:
config.load_paths << File.join(Rails.root, "app", "classes")
If you're using passenger or JRuby, you probably also want to add your path to the eager load paths:
config.eager_load_paths << File.join(Rails.root, "app", "classes")
The bottom-line is that once you get to a point in Rails where you find yourself asking this question, it's time to beef up your Ruby chops and start modeling classes that aren't just the MVC classes that Rails gives you by default.
Update: This answer applies to Rails 2.x and higher.
Update: The use of Concerns have been confirmed as the new default in Rails 4.
It really depends on the nature of the module itself.
I usually place controller/model extensions in a /concerns folder within app.
# concerns/authentication.rb
module Authentication
...
end
# controllers/application_controller.rb
class ApplicationController
include Authentication
end
# concerns/configurable.rb
module Configurable
...
end
class Model
include Indexable
end
# controllers/foo_controller.rb
class FooController < ApplicationController
include Indexable
end
# controllers/bar_controller.rb
class BarController < ApplicationController
include Indexable
end
/lib is my preferred choice for general purpose libraries. I always have a project namespace in lib where I put all application-specific libraries.
/lib/myapp.rb
module MyApp
VERSION = ...
end
/lib/myapp/CacheKey.rb
/lib/myapp/somecustomlib.rb
Ruby/Rails core extensions usually take place in config initializers so that libraries are only loaded once on Rails boostrap.
/config/initializer/config.rb
/config/initializer/core_ext/string.rb
/config/initializer/core_ext/array.rb
For reusable code fragments, I often create (micro)plugins so that I can reuse them in other projects.
Helper files usually holds helper methods and sometimes classes when the object is intended to be used by helpers (for instance Form Builders).
This is a really general overview. Please provide more details about specific examples if you want to get more customized suggestions. :)
... the tendency to make huge
ActiveRecord subclasses and huge
controllers is quite natural ...
"huge" is a worrisome word... ;-)
How are your controllers becoming huge? That's something you should look at: ideally, controllers should be thin. Picking a rule-of-thumb out of thin air, I'd suggest that if you regularly have more than, say, 5 or 6 lines of code per controller method (action), then your controllers are probably too fat. Is there duplication that could move into a helper function or a filter? Is there business logic that could be pushed down into the models?
How do your models get to be huge? Should you be looking at ways to reduce the number of responsibilities in each class? Are there any common behaviours you can extract into mixins? Or areas of functionality you can delegate to helper classes?
EDIT: Trying to expand a bit, hopefully not distorting anything too badly...
Helpers: live in app/helpers and are mostly used to make views simpler. They're either controller-specific (also available to all views for that controller) or generally available (module ApplicationHelper in application_helper.rb).
Filters: Say you have the same line of code in several actions (quite often, retrieval of an object using params[:id] or similar). That duplication can be abstracted first to a separate method and then out of the actions entirely by declaring a filter in the class definition, such as before_filter :get_object. See Section 6 in the ActionController Rails Guide Let declarative programming be your friend.
Refactoring models is a bit more of a religious thing. Disciples of Uncle Bob will suggest, for example, that you follow the Five Commandments of SOLID. Joel & Jeff may recommend a more, er, "pragmatic" approach, although they did appear to be a little more reconciled subsequently. Finding one or more methods within a class that operate on a clearly-defined subset of its attributes is one way to try identifying classes that might be refactored out of your ActiveRecord-derived model.
Rails models don't have to be subclasses of ActiveRecord::Base, by the way. Or to put it another way, a model doesn't have to be an analogue of a table, or even related to anything stored at all. Even better, as long as you name your file in app/models according to Rails' conventions (call #underscore on the class name to find out what Rails will look for), Rails will find it without any requires being necessary.
Here's an excellent blog post about refactoring the fat models that seem to arise from the "thin controller" philosphy:
http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/
Basic message is "Don’t Extract Mixins from Fat Models", use service classes instead, the author provides 7 patterns to do so