Suppose Author belongs_to Boook.
Is it possible to do the same as in Rails templates in a Freemarker template:
"author": ${book.author.last_name}
I tried without success. May be my syntax is wrong or I'm missing something ?
You would need to use the include() and pre-load objects for this.
Please, see: http://javalite.io/lazy_and_eager#eager-simultaneous-loading-of-parents-and-children
You would need to experiment with code a little. In the worst case, you can add a method to a model and call that from a template.
Related
I've just upgraded from Rails 5.0.0 to 5.1.1 and started getting a ton of deprecation warnings like this:
DEPRECATION WARNING: The behavior of changed_attributes inside of
after callbacks will be changing in the next version of Rails. The new
return value will reflect the behavior of calling the method after
save returned (e.g. the opposite of what it returns now). To
maintain the current behavior, use
saved_changes.transform_values(&:first) instead.
and this:
DEPRECATION WARNING: The behavior of attribute_changed? inside of
after callbacks will be changing in the next version of Rails. The new
return value will reflect the behavior of calling the method after
save returned (e.g. the opposite of what it returns now). To
maintain the current behavior, use saved_change_to_attribute?
instead.
I don't use those methods explicitely anywhere in my project and the warnings are pointing mostly at create and update calls on my models.
I believe it has something to do with my validations and after_update and after_create callbacks where I use confitions like if: { author_id_changed? } but I have no idea what to do with them.
I also believe the warning is related to this massive update to ActiveRecord.
Would appreciate any hand you can give with this.
UPD
This article helped alot!
Well, got around everything by running bundle update and updating the gems and also following this article and changing attribute_changed? calls in after_ callbacks (but not in before_ callbacks and validations) and switching from attribute_was to attribute_before_last_save.
For After callbacks, you can use saved_change_to_attribute?
For Before callbacks and validations, you can use will_save_change_to_attribute?
I hope this information will help!
I've done an upgrade to Rails 5.1.6 and have the same DEPRECATION warnings. If ever anyone still wants to solve this warning. Here are the steps I took:
Search all of your*_changed?
Changed this:
if name_changed?
...
if user_id_changed?
To this if it is inside after_* (after_save, after_commit, after_update, etc.) blocks:
if saved_change_to_name?
...
if saved_change_to_user_id?
AND to this if it is inside before_* (before_save, before_commit, before_update, etc.) blocks:
if will_save_change_to_name?
...
if will_save_change_to_user_id?
On my own opinion, this is quite tricky thing to change since we've been used to attribute_changed?. But change is good. The syntax also made more sense now.
You can change author_id_changed? to saved_change_to_author_id?
I had both namespaced controllers and models like this:
controller: Modules::Insurances
model: Modules::Insurances
This worked fine, but I want to remove the namespaced model back to normal, but keep the namespaced controller. I have removed all the references to "Modules::" in the models and also in all the activerecord queries in the controller to the model. When I visit the page, it returns this error:
Expected /***/app/models/modules/ins_insurance.rb to define Modules::InsInsurance
What should I do more to remove the namespaced model?
The root cause of the error is that rails is expecting the name of the class declared inside the file modules/ins_insurance.rb to be Modules::InsInsurance -- the filename must match the class name (after a little conversion thanks to the Inflector's underscore and classify methods: http://apidock.com/rails/ActiveSupport/Inflector/underscore). So name the file back to insurance.rb and you should be OK.
On a broader topic, I can only think you'll run into problems sooner or later by using a sub-directory called modules -- at the very least it's confusing between the Ruby keyword Module. If you're looking for a place to put general purpose code, use app/lib then require the file as needed. Namespacing is a fine thing to do, but you'll end up fighting with Rails unless you go with the flow. (Lesson learned the hard way ;-)
It appears there's not much documentation on Rails template handlers. There's the included handlers, like RJS, ERB, and Builder, which offer some assistance.
I'm trying to implement my own, and I've succeeded, albeit with a bit of weird code, or possibly there's something I don't quite understand.
class MyHandler < ActionView::Template::Handler
def call(template)
template.source.inspect
end
end
So what's weird is that I have to call inspect, otherwise Rails will try to eval the string as Ruby code.
I was under the impression that that's what include ActionView::...::Compilable did (which I'm not including in my code).
Now, if I make my template "compilable" (by using the include... statement), it still looks for the call method instead of the compile method.
So could anyone explain to me a bit more about how this works?
Thanks!
I've just been going through this problem myself. Basically rails expects the renderer's .call method to return ruby code that will render your template. It then dynamically generates a method which runs this code, and injects it into a module.
The module has all of the url/application helpers included, which means they're in scope for the template.
So, in answer to your question the solution is for .call to return some ruby code that outputs your rendered template as a string, or for it to render ruby code that invokes your template engine.
Check out tilt and temple, I have learnt a lot about template engines reading their code.
I am using ruby on rails 3. I have a model called Content. Within the controller, I extract some variables and pass them to the Viewer. In the Viewer, I would like to use of my self made functions so that I don't have too much logic and code in the Viewer. I defined these functions in the ContentsHelper module.
My functions defined in the ContentsHelper module are making use of ActionViewer helper functions, however these are not available in the ContentsHelper module. I am getting for example NoMethodError: undefined method content_tag' for #<Content:0x1025b9458> error.
How is it possible to make all the ActionViewer helper functions available?
Newbie.
following suggestion of Tim:
module ContentsHelper
include ActionView::Helpers
def bla
content_tag(:h2, self.title)
end
I can run the bla method as Content.bla in the console. This is perfect!
But when I replacec content_tag with image_tag, then I run into trouble and get this error:
NoMethodError: undefined method `config'
from /Users/sonat/.rvm/gems/ruby-1.8.7-p334/gems/activemodel-3.0.0/lib/active_model/attribute_methods.rb:364:in `method_missing'
from /Users/sonat/.rvm/gems/ruby-1.8.7-p334/gems/activerecord-3.0.0/lib/active_record/attribute_methods.rb:46:in `method_missing'
from /Users/sonat/.rvm/gems/ruby-1.8.7-p334/gems/activerecord-3.0.0/lib/active_record/attribute_methods.rb:44:in `send'
I can see that module that is responsible of the image_tag method is missing "something". I would appreciate if you guys tell me the general approach in finding what is missing and how I could solve the problem.
Looks like you're trying to do something odd like to use the helper method inside your model instead of inside your view. Helper methods are for views, not for models.
Added
Tim asked if I could provide some links to other resources, but really this is such basic stuff that I'm not aware of anything dealing with this. Mostly tutorials deal with unusual things like using helpers outside views.
So instead, here's some code:
app/helpers/contents_helper.rb
module ContentsHelper
def foo
content_tag :p, "Foo"
end
end
app/views/contents/index.html.erb
<h1>Listing Contents</h1>
<%= foo %>
The HTML output when going to /contents URL
<h1>Listing Contents</h1>
<p>Foo</p>
And that's as hard as it is.
content_tag:
Does this work?
module ContentsHelper
include ActionView::Helpers
end
image_tag:
Looks like you'll have to make your models know where the images are located by implementing a #path_to_image(image) method.
I've set up a Gist for us to mock out the features you need here:
https://gist.github.com/1015333
You should be able to download and run forNoNameNo.rb (which should run quietly without errors.)
That file has some examples of what's needed to make image_tag work.
further discussion:
Helpers are probably the weirdest part of Rails. They're declared at the controller level, but are only included at the view level, and rely on weird parts of the controller stack for their info; and yet, the info they are mainly concerned with presenting is the model info. So they're spread across all these weird concerns.
To deal with code-organizations issues arising from all of this, people have tended toward the Presenter pattern. (Also see rbates' version)
That said, if you'd prefer to stray off the beaten path in rails, it's normally really useful to read the source code.
If you're using textmate:
mate `gem which actionpack`../action_view
in Terminal.app should get your there. If you're using another editor/operating system you might have to navigate to whereever gem which actionpack tells you to go.
there is something that is disturbing me a bit about rails 3.
i am trying to upgrade my application from rails 2 to rails 3.
i followed all the steps necessary to do and things were working well for me till now except one thing:
i have a helper method that is defined differently in different helpers, for example it is defined in the application_helper in one way and the same method defined in a different way in the homepage_helper, and defined differently in another helper, let's say video_helper, in addition to that, it is used in a shared view that is used throughout the application, now if i am in the homepage, i want this function to get called from the homepage_helper and if i am in the video page, the function must be called from the video_helper, based on the concept of convention in rails, this worked perfectly in rails 2 but in rails 3, the function is always called from the last helper, alphabetically ordered, that is in the example, video_helper.
How can i fix this?
Kindly advice.
Appreciate all the help.
In rails 3 all helpers are always loaded.
You can either:
1) name your helpers differently.
2) Explicity define which helpers you want
3) Check the controller from the helpers to determine which helper to provide.
If I'm understanding your post right, you have something like
module ApplicationHelper
def error_messages
...
end
end
module VideoHelper
def error_messages
...
end
end
module HomepageHelper
def error_messages
...
end
end
And now you want to call error_messages from a specific helper and calling error_messages arbitrarily behaves differently from how it did in Rails 2. Am I right so far? If not, you can ignore the rest of this post =P
I just spent half an hour playing with the syntax and one of my projects in irb and the closest I could get was something along the lines of Posts::PostsHelper.helper_method, which works in irb if I 'include PostsHelper' first.
With that said, if you're willing to do something like Class::ClassHelper.helper_method, why not just rename "helper_method" so that it's unique to your ClassHelper? You're going to have to change each "helper_method" call to be specific to some helper anyways. I think this is a much cleaner solution