DRYing out Rails Flashcards
Add Validation to this..
Class Person < ApplicationRecord
end
Then call the validation.
Class Person < ApplicationRecord validates :name, presence: true end Person.create(name: "John Doe").valid? #True Person.create(name: nil).valid? #False
Spot the Error class Library < ApplicationRecord has_many :books validates_association :books end
class Book < ApplicationRecord
has_many :libraries
validates_association :libraries
end
The validations create an infinite loop.
Name the Validations you would use for these scenarios:
- A check box being marked
- I am creating a book which is of association library. I want to validate what is in library as well as book when creating a book.
- Two Text Fields should receive the same values, like password and confirm password.
- Validate that certain values are not included in a set.
- Acceptance Validation.
validates :terms_of_service, acceptance :true - Validates Associated
validates_associated :books - Confirmation:
validates :email, confirmation: true - Exclusion
validates :subdomain, exclusion: { in : w%(www}
What is Dry?
Don’t Repeat Yourself
How is validation Dry?
Well we would have to have a validity constraint and that could be put anywhere. SO we DRY it out by putting it in just the Model.
How can I see what didn’t pass validation?
m.errors[:release_date] will show me the errors of release data validation.
What are Lifecycle Callbacks?
Before you talk to the database, you can have these callbacks run. Like you can uppercase some of these things before the value hits the server. There are control on validations before the create. Or maybe an audit record or log entry after the validation. The point cuts are set though.
Can we put validations anywhere?
No we have certain places for validation and we must follow them. We also have to be cautious that we don’t know where the validation comes from
What are constraints on a controller action?
Typical is that you want to only be able to do stuff when you are logged in per say.
Setup a Filter in an application
class applicationController ‘login’
protected
def set_current_user
@current_user=Moviegoer.find_by_id(session[:user_id])
redirect to ‘/login’ and return unless @current_user
end
end
The Redirect terminates the default execution that would happen after the filter. The filter could unexpectedly get triggered though.
What does Protected do in the controller?
Prevents method from being called by any routes.
I have a route that I made in my controller, but it seems to not be working. When I debug I see that my controller method pertaining to that route never gets called. What could be happening?
I am not calling the right route. I am not calling the right redirect.
It is more likely that I have a before_filter somewhere in the code that is preventing the controller method from being called in the first place.
What is the scope a before_filter? of the ApplicationController before_filters?
The Filters declared in a controller also apply to all of its subclasses. That means the filters in ApplicationController apply EVERYWHERE.
Can a filter change the flow of execution?
Yes by calling redirect or render it can prevent the default controller method from a route from ever being called.
Compare Validations and Filters
Both Are Dry
Both are point cuts, but rails gets to determine where these point cuts are.
Only Filters can change execution flow
Filters capture errors in flash, validation captures errors in its errors object.
Which Ruby Language Features support Dryness enabled by validations?
Higher Order Functions, Closures, and Metaprogramming.
Metaprogramming cause you can turn the function name into a function reference at run time. Closures and higher order are usually together. Pass a function to validator is an example of higher order and closure.
What is Metaprogramming?
When you can write programs and treat them as your data. Write code as you run them is another plus. Modify itself while running.
What is the general rule of Third Party Application?
You never reveal the password and login.
Tamper-evident secure token?
String that when some of the characters are manipulated we can tell and we can invalidate them. You use a secret string that only I can decode. Then the tampered version won’t decode properly. Only someone with secret can make the code. The string doesn’t contain the actual password, just enough information for it.
Explain Process of 3rd Party Validation
- Tell the app you want to login with Twitter.
- Redirect to Twitter Login Page
- You OK to authorize the app
- User Agrees
- Twitter then provides an access token as a tamper-evident secure token. Use the token to make sure I authorize that the app does what user agrees to.
Session should centralize the logic that talks with the third party application. Session remembers the primary key. Session is also tamper-evident string.
Which is True with Authentication?
Requester can do anything you can do on a provider.
If your credentials on the requester are compromised. your credentials on the provider are compromised.
If provider revokes access, the requester no longer has information.
Access can be time-limited to expire on a pre-set date.
That last is true, Notice that the others are false.
What do you have to tell Omni-Auth?
- Where are you trying to authenticate to? Twitter, Facebook, Google, etc.
- Omniauth gem provides the routes to Twitter authentication. It then provides the logic and such for you. You just have to tell omni auth what site I want to authenticate.
- Then you have to get a developer key from the third party software. Then you put your auth key in a xaml file.
- Once you authenticate on Twitter it will redirect to something in my app and it will include the token. We need to provide the end route for the third party.
- Create ‘auth/:provider/callback’ route and ‘auth/failure/ routes
How do I get all the parameters sent back by the omniauth provider?
You just have to call request.env[“omniauth.auth”].
Example:
def create
auth = request.env[“omniauth.auth”]
user = Moviegoer.find_by_provider_and_uid(auth[“provider”], auth[“uid”]
or Moviegoer.create_with_omniauth(auth)
“provider” we know from omniauth, like Twitter.
“uid” we look and see this is what Twitter sends us.
What are reusable scopes in rails?
A movie that have some average score/rating. Movies with some certain rating. There are ways to prevent having to call a bunch of join statements.
Movie.for_kids
Movie.average_reviews
Example:
scope :for_kids, :conditions => [‘rating IN (:ratings)’, :ratings => %w(g PG)]
What is happening here?
scope :with_good_reviews, lambda{ |cutoff|
joins(:reviews).
group(:movie_id).
having(“AVG(reviews.potatoes) > #{cutoff}”)
}
end
This is in a lambda expression because I need to be able to evaluate this for a particular argument value, right. Instantiate at run time the right value for the cutoff.
The scopes are stackable as well.
If you call with_good_reviews then you get an error since you HAVE to call it with parameters.
When does the Query Happen?
The Query is deferred until the view because it can then check the cache to see if had been called earlier and then just render that value again without calling the query.
Query is Horizontal or Vertical Bottleneck?
Horizontal
When does the Database Query Happen? Controller? View? Controller: @m = Movie.for_kids_with_reviews
View:
@m.each do |movie|
In the View!