model name to controller name - ruby-on-rails

How can I get the controller name out of the object if I don't know what the object is?
I am trying to do:
object.class.tableize
but Rails says:
undefined method `tableize' for #<Class:0xb6f8ee20>
I tried adding demodulize with same result.
thanks

object.class.to_s.tableize

For semantic reasons, you might want to do:
object.class.name #=> 'FooBar'
You can also use tableize with this sequence, like so:
object.class.name.tableize #=> 'foo_bars'
I prefer it that way due to readability.
As well, note that tableize also does pluralization. If unwanted use underscore.
Hope it helps anyone, even if it's an old thread :)

Related

why am i seeing User::ActiveRecord_Relation instead of ActiveRecord::Relation? [duplicate]

Suppose I have a Rails model: class Project < ActiveRecord::Base
In the Rails console:
> Project.all
=> #<ActiveRecord::Relation []>
That seems reasonable. However,
> Project.all.class
=> Project::ActiveRecord_Relation
What is Project::ActiveRecord_Relation? Specifically,
How did it get "added" (namespaced into) to my model class?
How does it respond to is_a? correctly? Project.all.is_a?(ActiveRecord::Relation) returns true (which is expected), but is Project::ActiveRecord_Relation actually an instance of ActiveRecord::Relation, or is it something else?
Why do this? Why doesn't Project.all return an ActiveRecord::Relation, rather than Project::ActiveRecord_Relation?
(This is in the context of Rails 5.1, in case it's changed in older or newer versions.)
(I'm open to title edits if someone else can come up with a better title for this question)
Check this line of code from ActiveRecord.
https://github.com/rails/rails/blob/f40860800c231ecd1daef6cf6b5a8a8eda76478d/activerecord/lib/active_record/relation/delegation.rb#L23
mangled_name = klass.name.gsub("::", "_")
So, for your questions:
it get's added on activerecord's base when it extendes the delegation module https://github.com/rails/rails/blob/f40860800c231ecd1daef6cf6b5a8a8eda76478d/activerecord/lib/active_record/base.rb#L290
it's actually the same class, just something like an alias (not actually an alias, it's a constant with the class as value)
the class is actually an ActiveRecord::Relation, it's just that the name was changed
There are actually two questions you are asking:
How does it work?
Why is it like that? (What for?)
#arieljuod has already given you some explanations and a link.
However the second question is still unanswered.
There is another similar question exists which I hope will help you find all the answers:
How can an ActiveRecord::Relation object call class methods
It looks like the two questions (by the link and yours one) answer each other )
Take a look at #nikita-shilnikov's answer. Good luck in your investigation!

Reliable String interpolation in Rails

What is the best way to ensure that a model exists before doing string interpolation? I have a variable user, and I need to see what the user's major is. A table in between named user_attributes has the user's info.
#{user.user_attribute.major.name}
The user may not have specified a major yet, in which case they wouldn't have a major model instance yet. So when I try and get the name of the major, I would get an "undefined method on nil class type" error. Any advice on how to safely do this?
You could avoid try and add a method to your model or decorator..
def major_name
user_attribute.major && user_attribute.major.name
end
OR
def major_name
user_attribute.major.name if user_attribute.major?
end
Check: https://codereview.stackexchange.com/questions/28610/handling-nil-trying-to-avoid-try
You can use try method:
# if model is present
{user.user_attribute.major.try(:name)} # => "<MAJOR_NAME>"
# if model is NOT present
{user.user_attribute.major.try(:name)} # => ""
You can read more about try.
You could use the lonely operator. It is like try, but slightly less functional (which doesn't matter in your case).
user.user_attribute.major&.name
This might well be the 'worst' answer to ruby puritans, but it works for me in some scenarios:
"#{user.user_attribute.major.name rescue nil}"

Dynamic bang finders in Rails 4

Rails 4 is getting rid of dynamic finders, so
User.find_by_hash(hash)
becomes
User.where(hash: hash) # .first
Okay, not a big deal. But what is the best way to deal do with dynamic bang finders like User.find_by_hash!(hash) since there is no where!() method? Rails 4 Release Notes conveniently avoid this.
Update: It plainly says: "All dynamic methods EXCEPT for find_by_... and find_by_...! are deprecated."
Either the pages has changed since or I was blind when reading it.
I think the new syntax is
User.find_by!(hash: hash)
At least that's how ryanb does it:
http://railscasts.com/episodes/400-what-s-new-in-rails-4
Hope that helps.
Well, if you need a method that finds all but raises exception if the relation is empty, you can create such new method for your models yourself (or mixin to ActiveRecord::QueryMethods). Something like:
def where!(*args)
rel = where(*args)
raise RecordNotFound if rel.empty?
rel
end
It plainly says: "All dynamic methods EXCEPT for find_by_... and find_by_...! are deprecated."

Is there any way to define a model's attribute as always html_safe?

I have a model called Feature with a variable called body_string, which contains HTML markup I'd like to render, rather than escape.
Every time I reference body_string in my views, I need to use <%=raw or .html_safe. This seems redundant and not-so-DRY.
Is there any way that I can establish once-and-for-all the body_string variable as html_safe?
I'm assuming this would happen in the app/models/feature.rb file, but I can't figure out what the right syntax would be, exactly. I've thought of this:
def body_string
return self.body_string.html_safe
end
But Rails doesn't like it; it raises a stack level too deep exception.
Naturally I could define a variable/method with a different name:
def safe_body_string
return self.body_string.html_safe
end
And then just change all references in the views from body_string to safe_body_string. But somehow this seems almost as un-DRY as simply using raw or .html_safe in the first place.
Any insights to how best to handle this? I feel like there must be something really elegant that I'm just not seeing.
Just use read_attribute to avoid the recursive call to body_string:
def body_string
read_attribute(:body_string).html_safe
end
read_attribute is complemented by write_attribute for setting attributes from within your model.
A note on style: Don't use explicit returns unless you actually need them. The result of the last statement in a method is implicitly the value returned from the method.
While #meager's answer will definitely work, I don't think this logic belongs in a model. Simply because it adds view-level concerns (HTML safeness) to the model layer, which should just include business logic. Instead, I would recommend using a Presenter for this (see http://nithinbekal.com/posts/rails-presenters/ or find a gem for this -- I personally love Display Case). Your presenter can easily override the body_string method and provide the .html_safe designation when displaying in the view. This way you separate your concerns and can continue to get body_string from other models without mixing in the view concern.
Maybe this gem is useful for you. I also wanted to stop repeating html_safe all the time when the content is completely trustable.
http://rubygems.org/gems/html_safe_attribute
Or you can also use this approach,
def body_string
super && super.html_safe
end

How to DRY up a ruby conditional structure needed for Rails

I'm finding I often have to use a structure to avoid a Rails error of undefined method 'name' for nil:NilClass.
The structure looks like this:
if country.state
country.state.name
end
It seems like a classic case of repeating oneself with country.state appearing twice in one simple block. Is there any way to DRY this up?
Rails adds a try method to object that mimics object#send but does not raise an exception if the object returns nil.
I think the syntax is
country.try(:state).name
Well not really. One option is to install the andand gem, but introducing a dependency for this may be a little much.
Other than using the slightly more concise syntax of:
country.state.name unless country.state.nil?
I don't think there's a DRY way to do this with the information given. I would argue that if you can't be sure whether country.state is nil or not, you may want to look at the code responsible for setting that value and determine whether that's a normal case or whether a validator upstream should be catching that.

Resources