Calling models with _ us controllers - ruby-on-rails

I have a table in the model called pg_search_documents, how do I work with it in the controllers?
I'm trying like this:
def show
#search = PgSearchDocument.find(params[:content])
end
But the so-called "PgSearchDocument" seems to be wrong.

You need to make sure you have a model declared in your app. If you have not done so, create the following file:
app/models/pg_search_document.rb
class PgSearchDocument < ActiveRecord::Base
end
In Rails 5 you would use:
class PgSearchDocument < ApplicationRecord
end
Please note the following naming conventions in Rails:
Database table name is plural snake case: pg_search_documents
Model filename is singular snake case: pg_search_document.rb
Model class name is singular camel case: PgSearchDocument

Related

Rails STI override model_name in parent class for all subclasses

I am using STI in a Rails app and in order to not have to define routes for all subclasses, I put the following in each subclass:
def self.model_name
Mapping.model_name
end
In the above example, Mapping is the parent model name. Example:
class UserMapping < Mapping; end
Having to put this in each subclass is not very DRY, so I'm looking for a way to set that in the parent somehow, so that each class that inherits from the parent automatically has the model name set as the parent model name.
Perhaps there is even a better way to overcome the routing issue that arises from STI unrelated to setting the model_name - I'm open to suggestions!
Thanks in advance!
Put this in your Mapping class:
class Mapping < ActiveRecord::Base
def self.inherited(subclass)
super
def subclass.model_name
superclass.model_name
end
end
end
Afterwards, all child classes of Mapping will also inherit the parent's model_name.
Another option is to override the model_name method in the superclass to return a custom ActiveModel::Name:
class Mapping < ActiveRecord::Base
def self.model_name
ActiveModel::Name.new(base_class)
end
end
By default model_name passes the current class as the first argument to ActiveModel::Name.new, so each sub-class will receive a different name based on their class. ActiveRecord models have a base_class method which we can use instead to get the base of a single-table inheritance hierarchy.
If you cared to, you could also name it something completely different. This might be useful when you're trying to transition a model to a new name:
class Mapping < ActiveRecord::Base
def self.model_name
ActiveModel::Name.new(self, nil, "AnotherMapping")
end
end
More in the docs

How to share constants between controller and model Ruby on Rails

Is it possible to share constants between controller and model?
e.g. in product.rb I have
PRODUCT_TYPES = %w[one two]
I want PRODUCT_TYPES constant to be available in the controllers as well.
As per my consideration your Product model looks like
class Product < ActiveRecord::Base
PRODUCT_TYPES = %w[one two]
end
You can access the given constant in the controller as below
p.product_type == Product::PRODUCT_TYPES[:one]
I deeply explained the various possibility in this answer
You basically have 3 possibilities:
global scope (initializer)
application scope (using the application module created by Rails)
class scope (defined them where you want, and call them with Class::CONSTANT)
We can access model constant in Controller as bellow...
class Invoice < ActiveRecord::Base
STATUS_PAYABLE = %w(APPROVED OPEN)
end
Controller use like ..
Invoice::STATUS_PAYABLE.include?('OPEN')

Rails gets wrong class when two classes have the same name

In my Rails I have the following models:
A STI sub-class
class Subscription::Discount < Subscription
def self.new_with_url
...
end
end
and another model class (doing completely different things, this is a STI base class)
class Discount < ActiveRecord::Base
end
So in my controller, I uses Subscription::Discount when I create users:
#user.subscription = ::Subscription::Discount.new_with_url()
However it complains: undefined method 'new_with_url' for #<Class:0x007fbb499c6740>
I think Rails is not calling the right class with new_with_url. On top of that I am not sure what #<Class:0x007fbb499c6740> is. So, two questions:
Without renaming any model, how can I reference Subscription::Discount properly?
Why is the error message saying #<Class:0x007fbb499c6740>, I can understand if it is Discount instead of that anonymous class.
EDIT:
Here are all the relevant models:
app/model/discount.rb
app/model/coffee_discount.rb (CoffeeDiscount < Discount)
app/model/subscription.rb
app/model/subscription/discount.rb (Subscription::Discount < Subscription)
The method is named create_with_url but you're calling new_with_url.
Fix the method name.

Handling forms with class table inheritance models

I would like to use form_for except I have class table inheritance models using the citier gem. They are defined as such:
class Fruit < ActiveRecord::Base
# calories:integer
# color:string
end
class Apple < Fruit
# is_sauce:boolean
end
class Banana < Fruit
# is_peeled:boolean
end
The problem is that I want the first part of my form to fill out attributes for my Fruit model. Then depending on a select field on what type of fruit (Apple, Banana), I then want to fill out attributes for that particular model yet I still want validations with the form_for helper. Any suggestions on how I can approach this... or additional clarification? Thanks.
What I ended up doing was asking for the model before creating the form. Then using many partials.

Where to put model "utility" functions in Ruby on Rails

I have a rails app with several models.
I have a function that I want to access from several models.
What's the best place to put this code and how can I make it accessible from the models that need to get at it?
My understanding is that helpers are just for views. Is this correct?
It seems wrong to create a plug-in and put it in the vendor folder - this is my code and integral to my app. Is this correct?
Thanks.
The simplest solution would be to create a module under lib and mix this into the models that need it, for instance, in lib/fooable.rb:
module Fooable
def do_foo
end
end
And then in your various models:
class MyModel < ActiveRecord::Base
include Fooable
end
No need to require fooable.rb, the Rails autoloading mechanism will find it for you as long as it's named using correct conventions.
In order to lessen the repetition of code, you could also create a main class which would include that module and the simply inherit from it from every model you'd like to share the behaviour.
Something like:
module Fooable
def do_foo
end
end
class ParentModel < ActiveRecord::Base
include Fooable
end
class Product < ParentModel end
class User < ParentModel end
class Item < ActiveRecord::Base end
Thus, in that example, both Product and User would share the do_foo functionality and Item would not.

Resources