Avoid using Rails models in migration.
- Models might have some
lifecycle callbacks which we dont want to be invoked in a migration.
- As we know what we are doing we dont want to deal with
- Model names can change irrespective of db table.
- Try to use
raw sql as close as possible.
Squash them after a period of time.
- To my experience over a period of time these migration files are painful and useless.
rake db:migrate might take a few seconds, or creating of a new database might take a few minutes when these files are big. Consider using tools like squasher.
Make them irreversible.
In Production it makes sense to have IrreversibleMigration as the code is tested in lower environments. If there is an issue try to fix it with a follow up migration.
Note: If there is a new developer in your team and setting up their environment. Let them do `rake db:schema:load` to get latest db copy.
I dont think i used
after_validation ever as
before_save(or similar callbacks like before_create or update) is the one which fits. Usually the flow is
before_save seems to be the last step in the process and by the time it reaches there the record is valid. Like you wanted it to happen every time when validation is successful.
after_validation is called irrespective of the validation failed or not. I cant think of a scenario where you want to use it.
We cannot substitute
before_save as we can not guarantee that the record is always going to be valid.
class Booking < ApplicationRecord
belongs_to :order, polymorphic: true
class PickupOrder < ApplicationRecord
has_many :bookings, as: :order, dependent: :destroy, inverse_of: :order
class DeliveryOrder < ApplicationRecord
has_many :bookings, as: :order, dependent: :destroy, inverse_of: :order
I can load all bookings along with orders like this
Now if I want to search list of bookings by `order_name` like `ja`
Booking.includes(:order).references(:order).where("order.order_name ilike %ja%")
Throws the error
ActiveRecord::EagerLoadPolymorphicError: Cannot eagerly load the polymorphic association :order
Solution: Do it in sql. with left outer joins.
Booking.joins("left outer join delivery_orders on delivery_orders.id = bookings.order_id and bookings.order_type='DeliveryOrder'").
joins("left outer join pickup_orders on pickup_orders.id = bookings.order_id and bookings.order_type='PickupOrder'").
where("pickup_orders.order_name like '%ja%' or delivery_orders.order_name like '%ja%'")
Have you ever encountered this error while working on
`DEPRECATION WARNING: In XXX class you exposed a `has_one` relationship using the `belongs_to` class method. We think `has_one` is more appropriate. If you know what you’re doing, and don’t want to see this warning again, override the `belongs_to` class method on your resource.
If yes this post is for you. Dont break your heads its on `jsonapi-resources`.
It looks like jsoapi-resources did not implement the `belongs_to` as how it should be. At least as of this writing (0.9.0v). It treats `belongs_to` and `has_one` relations in the way. here is the source which points to this. So for time being change your `belongs_to` to `has_one` and you are gold. Happy coding!
Hi all recently we got a task to integrate with a 3rd party api, get data and display on our site. It is taking 5-10 secs to get response from it. We went on trying ActionCable first as our backend is rails thinking that it gets us running without much integration hassle.
We ended up having bad experience with it. My recommendation is to not to go for ActionCable at any case. Rails community included this in Rails 5 but the client library is poorly written. As per this writing the Rails 5.2 also doesn’t have any updates to ActionCable.
- Annoying Reconnections: ActionCable has this class called Connection which is used for authentication and establishing a connection. The client library has a connection monitoring pool which runs for every 3 secs. There is no way to know why the server rejects the connection as it returns 1006(forceful disconnect). Still the client continuously tries to establish the same connection again and again which is frustrating.
- Not flexible: We look into ActionCable as a solution for websockets. Its just an option if you are using traditional Rails application (though it doesnt scale). It is so tightly coupled that we cant use it with any other websocket client library.
We ended up using Pusher which i discussed in this post.
Whats the issue?: There are many Rails servers that are multi threaded. Lets take the example of Puma, it uses threads pool. The default thread count is 16. This means the server can server 16 requests concurrently.
This is sufficient for normal applications. But if you are integrating with a third party services which is going to take long time for response you have the risk of taking the site down if all the threads are used at the same time. Take a look at the following picture.
If a hacker tries to hit the site with multiple(more than the thread count) concurrent 3rd party api requests the site goes down when once the threads gets exhausted.
Whats the solution:
We can fix this by request pooling which is not a recommended solution. I recommend websockets is way to go. They are light weight(as they dont carry more information in request headers) and can have a two way communication once connection is established.
It doesn’t exhaust you thread pool.
There are many ways to implement web sockets. Check this post which has a detailed explanation of different ways.
I personally have burnt my hands trying to use ActionCable for Rails + F/E framework app. You can find it here.
Having said all this i found another solution Pusher . After getting mad at ActionCable i found Pusher to the rescue. I recommend pusher for following reasons.
- Maintenance: As we communicate through Pusher api we dont need to worry about websocket server. No need to worry about socket connection errors.
- Ease of Integration: Pusher has api to integrate in almost all the languages. It takes less than 5 mins to use it when you signup.
- Usage: Their free account gives us adequate amount of messages per day. Good for us to try it.
I tried to add an index to a column and failed. After digging deeper these are my findings.
In rails migration if we want to add index to a column there are 2 ways.
- While creating a new table you can specify
create_table :users do |t|
t.string :name, limit: 30, null: false
t.string :password, null: false, limit: 20
t.string :email, null: false, limit: 20, index: true
- In all the remaining scenarios(add/update new column) we need to explicitly mention
add_column :users, :employee_number, :integer
add_index :users, :employee_number
index: true works only when creating new table. Hoping this is helpful.
Trying to save some others going through this pain. I have a parent and child associations both in the same form.
In parent i added `accepts_nested_attributes_for :child` and thought its going to take care of everything which is wrong. This helps in `create` and `update` but not in `delete`. To delete the child association you need to mention allow_destroy: true
accepts_nested_attributes_for :child, allow_destroy: true