How are you supposed to find the different options you can pass to methods in Rails? For instance I want to know the options I can pass to validates. I can't find them nowhere in the documentation.
api dock is useful and it also shows the source code http://apidock.com/rails/ActiveModel/Validations/ClassMethods/validates
As you know it's not possible to document hash options in the signature so you must either rely on the quality of the documentation or read the source code.
In this case the docs show some examples that cover pretty much all the default validators. Note that it cannot document all the available since they can be expanded dinamically.
>> ActiveModel::EachValidator.descendants
=> [Paperclip::Validators::AttachmentSizeValidator, ActiveModel::Validations::WithValidator, ActiveModel::Validations::ExclusionValidator, ActiveRecord::Validations::AssociatedValidator, ActiveModel::Validations::ConfirmationValidator, ActiveModel::Validations::PresenceValidator, ActiveModel::Validations::FormatValidator, Paperclip::Validators::AttachmentContentTypeValidator, Paperclip::Validators::AttachmentPresenceValidator, ActiveRecord::Validations::UniquenessValidator, ActiveModel::BlockValidator, ActiveModel::Validations::NumericalityValidator, ActiveModel::Validations::AcceptanceValidator, ActiveModel::Validations::InclusionValidator, ActiveModel::Validations::LengthValidator]
Or:
ActiveModel::EachValidator.descendants.map { |klass| klass.name.split("::").last.sub(/Validator$/, '').underscore }
=> ["attachment_size", "with", "exclusion", "associated", "confirmation", "presence", "format", "attachment_content_type", "attachment_presence", "uniqueness", "block", "numericality", "acceptance", "inclusion", "length"]
The starting point is always the official Rails documentation. For instance, here's the documentation of the validates method.
However, keep in mind that Rails is a constantly evolving framework. Unfortunately, this means that not all methods are fully documented and sometimes you need to dig into the source code directly to understand how a method works.
Related
I am currently splitting some code out to make it more reusable, and other code more succinct.
I realize I am passing a good bit of options into the locals hash, besides just the form variable, and all of these seem to only apply directly to the input object I am creating.
I was thinking of merging the locals hash into another that contains some defaults, and passing that to the input creation function.
After some researching API docs like these:
Ruby on Rails - API - ActionView::Renderer
Ruby on Rails - API - ActionView::PartialRenderer
and digging around to find these last 2 methods in the stack trace:
From: .../.rvm/gems/ruby-2.1.5#ux-rails3.2/gems/actionpack-3.2.22.5/lib/action_view/template.rb # line 145 ActionView::Template#render_without_mini_profiler: ... 2.1.5 (#<ActionView::Template:0x007fa41e138cc8>):0 >
From: .../app/views/shared/_checkbox_group.html.erb # line 3 ActionView::CompiledTemplates#_app_views_shared__checkbox_group_html_erb___4197967411385159258_70171427980900: ... 2.1.5 (#<#<Class:0x007fa40f30fec0>:0x007fa40fe71c50>):0 >
RVM, Ruby, Rails, Formtastic, Pry, Byebug, & Pry-Byebug.
Old, not-so-helpful workaround answer
As it may be convenient from the question's phrasing, one method is to not spend time diving into the Rails template rendering framework code and documentaion, and instead simply provide the options I mentioned for the locals hash, inside of a single property containing a new hash containing them, and pass that into the template.
Later I use that hash to merge with the default hash I had inside of the template and pass that to the input function as normal.
I could leave the Q&A here in case there might still me reasons people would want to directly access the locals hash, or could even develop an alternative approach that would be possible as well.
Update
So I dove into the Rail template rendering framework...
Exposition
I started simply taking this:
2.1.5 (#<#<Class:0x007fc01d352e08>:0x007fc018879698>):0 > self.class
=> #<Class:0x007fc01d352e08>
That wasn't much helpful, then went up into actionpack-3.2.22.5/lib/action_view/template.rb:145 to find this:
2.1.5 (#<ActionView::Template:0x007fc011e90510>):0 > method_name
=> "_app_views_shared__adrad_index_html_erb___3381877171036202789_70231455466120"
2.1.5 (#<ActionView::Template:0x007fc011e90510>):0 > view.method(method_name.to_sym)
=> #<Method: #<Class:0x007fc01d352e08>(ActionView::CompiledTemplates)#_app_views_shared__adrad_index_html_erb___3381877171036202789_70231455466120>
2.1.5 (#<ActionView::Template:0x007fc011e90510>):0 > view.method(method_name.to_sym).source_location
=> ["<our project_path>/app/views/shared/some.html.erb", 0]
Where the last point wasn't great, but then I started looking for ActionView::CompiledTemplates, which unfortunately, you cannot use source_location to find, or instance variable declarations for that matter (different issue :) ).
I decided to randomly search the actionpack-.../lib/action_view/ directory to find a reference or so in context.rb, but instead of looking inside of template.rb, I skipped straight to searching for locals in that gem's files now.
resolver.rb did not help much, and neither did template_renderer.rb.
Once I delved into template.rb and found the familiar above stack frame for render that my answer had to be between that and my actual page with the included locals properties,
I followed compile! to its definition,
saw a familiar ActionView::CompiledTemplates,
then a compile,
found an interesting arbitrary, literal, meta source manipulation, as I was sort of expecting with the lack of more stack frames in-between to scour, and the callback-esque naming scheme, I found this curious variable, as a parameter to the dynamically-generated template function: local_assigns.
I quickly jump around to locals_code's definition since it is also used and verify this is source variable enumeration I was looking for!
Answer
local_assigns!
Also, I currently don't believe the hash provides any properties I would want to avoid, such as any information specific to only the current partial template page that I wouldn't want to be propagated to the child partial template page.
Update
I am starting to do more with this variable, and I wonder if I am limited.
I want to mix-in some default values, which might involve using binding.local_variable_set, but it is not able to create new local variables (How to dynamically create a local variable?), so I might just have to use my own nested data structure now..
Let's say I'm in a really huge project and am curious how this line works:
authorize! :read_pipeline_schedule, user_project
authorize! is supposed to be method name. Is it a private function in the class, or DSL provided from a parent block, or including, or declared in a gem? Or maybe none of them?
I was using grep to find internal code and Google for external code such as gems, however I guess it's useful if I can see the call stack of the method. puts caller is printing from the place where I am although it can not be used for analyzing the above case.
I'd like to know the best practice.
You can grep your code and installed gems and, if name is unique enough, you'll quickly locate its definition and associated usages. However, if a name is a common one, like call, then this approach is useless.
Ruby is a dynamic language and, as such, is a nightmare for static analysis. You may guess where this comes from, but you just can't know for sure.
The only way to know is runtime introspection. So, in your example, put a breakpoint right before that line
binding.pry
authorize! :read_pipeline_schedule, user_project
You'll drop out to pry shell. Now you can do
show-source authorize!
And see where exactly this method is defined.
The easiest way is to ask the method itself:
method_object = method(:authorize!)
method_object.owner
# => returns module in which the method resides
method_object.source_location
# => returns file name and line number of source code where the method is defined
Note that source_location may return nil for methods which have no Ruby source code, e.g. dynamically generated methods or methods implemented in the interpreter internals (C functions in YARV, Java methods in JRuby, etc.)
I like caller(0), caller_locations, and the ever-incredible show-source
I am using the decimal type in Rails for storing currency.
However, I am tired of constantly seeing results like:
nominal_amount: #<BigDecimal:7f919884b648,'0.7E6',9(18)>
When I use the Rails console.
I can fix this by defining inspect as def inspect; to_s; endon BigDecimal, but I am concerned that it could lead to peculiar bugs.
Anyone who can vouch for or warn against this monkey patch?
Ruby Doc suggests to override inspect for user defined classes. It returns a human readable string. No other code should rely on the functionality of inspect. So if you decide, that it is more human-readable - to you - if you change the default behavior it is okay. As long as you don't include it in a gem or other code foreign developers will use.
http://ruby-doc.org/core-2.1.1/Object.html#method-i-inspect
Hmm, if you put it in an initializer and run it in dev mode only... I don't see any risk. There is a chance someone else's code counts on BigDecimal.inspect returning an object string. I would say it's a development only modification.
inspect "Returns debugging information about the value as a string".
See apidock.com/ruby/BigDecimal/inspect
I doubt that overriding debugging output format can break anything. I'm monkey-patching it to to_s as well.
This is a very basic ruby question. What is the difference between ClassName#message and ClassName.message?
I am reading a basic Ruby guide and I see both references used quite a lot. It seems that mainly in the code ClassName.message is used but in the documentation ClassName#message is used.
Is the # simply documentation convention? Will only the . work for message passing in actual code? Or is there something that I am just missing?
Does the meaning differ in Rails at all?
In code you use object.method. In documentation however, Class#method denotes an instance method (e.g. String#upcase), whereas Class.method or Class::method denotes a class/module method (e.g. Math.log10).
The # is used in the documentations to point out the difference between class methods and instance methods.
In the code, you'll be using . in all the cases.
'#' is rails convention. In rails className#Message will map to Message action of your className controller.
Ex:
match "profile" => "users#show"
This will map root_path/profile => Show method(or action) of UserController.
I have a rails 2.3.4 app and a line that looks like:
temp = Rails.cache.fetch(:temp_id) { User.find_by_name('Temp').id }
and everything worked fine, until I decided to switch the caching layer to memcached by adding the following to my environment.rb:
config.cache_store = :mem_cache_store
Now the line which used to work fine gives me the following error:
undefined method 'length' for :temp_id:Symbol
/usr/local/lib/ruby/gems/1.8/gems/activesupport-2.3.4/lib/active_support/vendor/memcache-client-1.7.4/memcache.rb:645:in 'get_server_for_key'
I understand the error, but I would imagine this common case would have been quickly discovered by a rails test case, so I am wondering if I am doing something wrong. Otherwise, I'm sure I can monkeypatch this issue to convert the symbol to a string.
Thanks
Just use string keys if you can. All the documentation examples use string keys. Although it's not explicitly mentioned as far as I can see, other keys are not supported.
The key arguments are passed directly to the cache implementation, so the different caching flavours may disagree on whether or not they accept anything other than strings.
Because the caches are external with the exception of in-memory cache, I'm not sure that supporting symbols would be useful apart from preventing cases like yours. The key will actually be written to some output somewhere (it's not just internal to your Ruby app), so conceptually the key should be a string.
Edit in reaction to comment: yes, it is of course possible and perfectly reasonable in this case to create a monkey patch to circumvent having to change all calls. What you're suggesting is this (copied into the answer for readability):
class MemCache
def get_server_for_key_with_symbols(key, options = {})
key = key.to_s if key.is_a? Symbol
get_server_for_key_without_symbols(key, options)
end
alias_method_chain :get_server_for_key, :symbols
end
I would also consider just doing a project wide search-and-replace for \.fetch(:\w+) and replace it with \.fetch("$1") (repeat for read and write if necessary). This should probably cover 95% of all cases and a subsequent run of your test suite should catch the rest of the errors.
In general: While the documentation of Rails is pretty good these days, a lot of assumptions are unfortunately still implicit. It's generally a good idea to take a good look at the examples that are given in the documentation, and use the same style. The documented examples are always how the framework was intended to be used.
FWIW, it's canonically Rails.cache.read and Rails.cache.write.