Have you got any solution for cropping landscape and portrait images ?. I am working on cropping different sizes of images. It is not working for me. Could you help me please. I was struck up with from 2 days.
I love railscasts, but not this episode. I think it is wrong that "testing is out of the scope of this episode". You should have had tests at the start of the refactoring and ran them instead of going to the browser all the time.
It is about the mind set.
A lot of times we need to get some tings up in a hurry, and skip testing (because it is out of the "scope of things").
I guess almost all rails developers in the world watch railscasts. So, railscasts has a responsibility to show the "right" work flow.
I understand that the episode is a bit long. But it would be better and shorter if you skipped the sign_up form and did TDD on the PasswordForm.
country has_many states
state belongs_to country
state has_many peoples
people belongs_to state
In this case the _form file in people view should contain a collection_select for countries which do not affect the database, but it is only used to populate the collection_select of states.
Hi,
Could use a second opinion on this - I have an IF statement block in my UJS file - and the if condition is not satisfied (confirmed by putting a js alert in there) . However - the block seems to get executed - the console is showing the database queries in that block being executed. Cant seem to make sense of it - thoughts ?
I was actually getting the same problem, and I had to remove the ENV[] from the KEY and SECRET inorder to get it working. Just adding the callback didn't work.
@Minh-Tue Every time you go to the server you get a session, and every session can have any arbitrary amount of objects stored on the server as session variables. Further, the server is smart enough to give every user their OWN session with a distinct ID. When you see things like 'session[:user_id] = user.id' it is just telling the server, essentially, "Create a new session variable named user_id and assign it the value of user.id." You can do this for anything you want, naming your variable anything you want -- for example, if your user table had a firstname column you could do session[:cool_name] = user.firstname and then use session[:cool_name] wherever you wanted to display the current user's firstname.
As far as multiple users go, the server writes a cookie to your browser with your unique session ID in it, which is how it keeps track of which session variable values to return to you so that you see your firstname, and not the value of session[:cool_name] for some other user.
You have mentioned that for minimal proposes (installing chef) you compile ruby from source and later on RVM can be installed with recipe.
Is there a common method to install RVM through chef? I didn't find something popular among the community cookbooks.
Finally, after installing RVM, how do you make sure that everything runs through the ruby version installed through RVM?
I have to disagree with some of this concept: Now the validations apply only to those forms, so if you somehow introduce another way to sign up (maybe an email gateway auto creates?) your validations do not run. I think in many cases it would be better to leave the the non form specific validations on the model and delegate them.
This guy: (in the Uploader) is where you set the default image.
ruby
# Provide a default URL as a default if there hasn't been a file uploaded:defdefault_url"/images/fallback/" + [version_name, "default.png"].compact.join('_')
end
Note to all using FriendlyId for pretty URLs. In any view to create an new image be sure to change <%= link_to "New Image", new_image_path(:x_id => @x) %> to <%= link_to "New Image", new_image_path(:x_id => @x.id) %> or else you spend countless hours trying to figure out why it just won't work.
True. But for the most part it doesn't make sense from a standpoint of clarity and natural language. Let's say you have model Product and you want a service object that will handle pricing on some complex criteria (geolocation, color, shipping, moonphase, etc). It would be a good candidate for a service object ProductPricingService. You wouldn't just call it Price or Pricing. First of all it's ambigious. Pricing of what? Products that you sell? Pricing you get from vendors? Pricing of gas today? And if you were to argue that this Service object could be used by many models, then you are defeating the purpose of Service Object. I'm exaggerating of course. But the whole point is to create clear and maintainable code. So while you can save some keystrokes by naming it Price, it's much more clear to another person ( and you in 5 months) if you name it ProductPricingService.
Q2
For instance let's say you have model Product. you have methods like :
If this is the only method that deals with labels you have and it's that simple than creating a Service object is an overkill. However if your method becomes complex or you find that you need multiple method for related things:
You could just patch the gem up to your own liking.
F.e.:
Add a column to the tag table (rails g migration AddDescriptionToTag description:text)
Open up the class (ActsAsTaggableOn::Tag) and go from there - make the description accessible or whatever you want.
This is very appropriate for apps backed by web services where the app may not have a direct database connection. I'm currently working on such an app and the API serves JSON, so building form objects that are custom for the purpose is definitely the way to go. Thanks for showing us this technique.
Ryan, definitely have to agree with some of the others that you have a very uncanny knack for always going over issues I'm working on right now. I had a simple signup form that created an account and user which works but the code isn't as "elegant" as I would like. However, I think a form object would be more complex for my simple use case.
But this gets me thinking in that fashion; instead of throwing it all into one big object because it's all "related", I'll now be thinking about ways to separate logically-related chunks of code into separate objects. Did like the fact that you could "enforce" strong parameters by individually assigning values...it's something I innately knew but didn't fully realize until you pointed it out.
Really enjoy the casts on refactoring/organizing code. They help me a lot as I tend to write it for a deadline, and then maintain it later.
This is a great episode! 2 years later and still very relevant.
However, I found that using Redis as my I18n score has a noticeable performance cost - even when running on the same server as my Rails app. I wrote a very simple key-value cache gem that memoizes the translations. In my case it greatly improved my site's performance.
Hey Ryan, thanks for the great tutorial.
There is one issue with auth permissions. current_user variable defined in application controller doesn't fully works with this standart Auth protection to access just a current actions in controller:
class SomeController < ApplicationController
before_filter :authenticate_user!, :except => [:action]
...
Thanks, this is really well done and helpful. I especially like that the whole process is a refactoring of old code. I've found it difficult to design loading, authorization, presenters, service_objects, etc. into the beginning of a complex project. It always seems to work better to refactor code as it becomes complex into a set of objects that work well together. Form objects must really work well with form builders and form presenters.
I can tell that the apache.conf included with the code in config directory is being symlinked in sites-available. But why is this necessary? I have already setup my apache by adding the exact same virtual host in my 'sites-enabled' directory and it works. So why copy it in sites-available, especially if apache doesn't read the config form that directory?
Yes I did. May have commented below somewhere but this is a windows specific problem because it doesn't support agent-forwarding. If you need more help I wrote everything down, but in short:
Make sure the postgresql database owner and password match the deployer username & password.
Then, I also needed to add
run "chmod +x #{release_path}/config/unicorn_init.sh"
to the symlink_config, so it would remember it has permission.
Set up the git repository on your vps, since again it won't forward from git.
How would you write an integration test for this? I'm having trouble because it no longer redirects to the new action:
http://stackoverflow.com/questions/16993366/testing-carrierwave-file-uploads-to-s3-with-capybara-and-rspec
Hello Hau,
Have you got any solution for cropping landscape and portrait images ?. I am working on cropping different sizes of images. It is not working for me. Could you help me please. I was struck up with from 2 days.
Thanks, this solved all issues I was having with bootstrap plugins :)
Still getting issues with this, dropdown's aren't triggered after page change
I love railscasts, but not this episode. I think it is wrong that "testing is out of the scope of this episode". You should have had tests at the start of the refactoring and ran them instead of going to the browser all the time.
It is about the mind set.
A lot of times we need to get some tings up in a hurry, and skip testing (because it is out of the "scope of things").
I guess almost all rails developers in the world watch railscasts. So, railscasts has a responsibility to show the "right" work flow.
I understand that the episode is a bit long. But it would be better and shorter if you skipped the sign_up form and did TDD on the PasswordForm.
Does anybody have an example of extending this example with at least one more controller?
+1
Thanks for the nice tutorial.
I'm wondering if dynamic selects could work also when the model structure is similar to episode #196, with some fixes.
For example model like this (similar to surveysays):
table "countries"
t.string "name"
table "states"
t.integer "country_id"
t.string "name"
table "people"
t.integer "state_id"
t.string "name"
country has_many states
state belongs_to country
state has_many peoples
people belongs_to state
In this case the _form file in people view should contain a
collection_select
for countries which do not affect the database, but it is only used to populate thecollection_select
of states.This should be very useful!
Hi,
Could use a second opinion on this - I have an IF statement block in my UJS file - and the if condition is not satisfied (confirmed by putting a js alert in there) . However - the block seems to get executed - the console is showing the database queries in that block being executed. Cant seem to make sense of it - thoughts ?
Heroku does not recognizer ENV variables on precompile.
You should move this 'coffee' code to the layout in order for this example to work,
did anyone figure out how to get it to work with ruby 2.0?
Is it just me, or it doesn't work in 2.0?
I was actually getting the same problem, and I had to remove the ENV[] from the KEY and SECRET inorder to get it working. Just adding the callback didn't work.
You are welcome :)
How about model caching and I18N (translation).
Is there an easy way to cache content of a multilanguage site?
So I guess this episode needs to be revisited as selects don't work with includes nowdays...
Rob, I know this is a year old but did you ever get some decent tests going for this?
Welcome back, Ryan!
Awesome episode!
if the user has a longer list of attributes, this might make the code cleaner:
@Minh-Tue Every time you go to the server you get a session, and every session can have any arbitrary amount of objects stored on the server as session variables. Further, the server is smart enough to give every user their OWN session with a distinct ID. When you see things like 'session[:user_id] = user.id' it is just telling the server, essentially, "Create a new session variable named user_id and assign it the value of user.id." You can do this for anything you want, naming your variable anything you want -- for example, if your user table had a firstname column you could do session[:cool_name] = user.firstname and then use session[:cool_name] wherever you wanted to display the current user's firstname.
As far as multiple users go, the server writes a cookie to your browser with your unique session ID in it, which is how it keeps track of which session variable values to return to you so that you see your firstname, and not the value of session[:cool_name] for some other user.
Hi Ryan,
thanks for one more nice video!
I don't like to remove everything from Models and put it inside another class. At the end the Form Object's classes will do a lot.
I prefer to remove only the logic from the Model and keep all validations, callbacks, and stuffs like that there.
I forked your code and implement what I think is necessary to remove from Model: https://github.com/willian/416-form-objects/tree/master/signup-willian
What you think about it?
Thanks again,
Yes, Adam, it is.
Can you please show how to display the reviews?
I can't figure out how to access embedded documents like reviews in this case...
i managed to integrate refinery cms with existing rails App.
my issue is that all the existing pages before can not be displayed on the refinery cms pages (backend).
Any help on how to override will be highly appreciated
Another great screencast!
You have mentioned that for minimal proposes (installing chef) you compile ruby from source and later on RVM can be installed with recipe.
Is there a common method to install RVM through chef? I didn't find something popular among the community cookbooks.
Finally, after installing RVM, how do you make sure that everything runs through the ruby version installed through RVM?
Thanks!
I have to disagree with some of this concept: Now the validations apply only to those forms, so if you somehow introduce another way to sign up (maybe an email gateway auto creates?) your validations do not run. I think in many cases it would be better to leave the the non form specific validations on the model and delegate them.
Guys, you may wanna check out this fix for the CSRF issues: http://stackoverflow.com/questions/10351386/rails-doorkeeper-cant-verify-csrf-token-authenticity?rq=1
i need that feature also!, would love an example for using rabbitmq or something like that.
Use model.image.url
Using to_s breaks the default_url.
This guy: (in the Uploader) is where you set the default image.
Note to all using FriendlyId for pretty URLs. In any view to create an new image be sure to change
<%= link_to "New Image", new_image_path(:x_id => @x) %>
to<%= link_to "New Image", new_image_path(:x_id => @x.id) %>
or else you spend countless hours trying to figure out why it just won't work.Thanks, Ryan! This was great!
+1 for nested resources! I'm having trouble commenting though. When I tried create a new comment in something like users/1/nested/12/comments/new
I get redirected to
nested/12/comments and users/1/ disappears
and then I get error saying
undefined method `classify' for nil:NilClass
in my CommentsController#create
How do I solve this issue?
I am trying to combine the information from episode 235 and this episode. I am unsure what to set the routes as. By following 235 my route is :
Following this episode, my routes would be :
If I follow 235 and try to combine it here, do I need to override the devise session controller create method?
I ultimately need to do all this via ajax.
Q1
True. But for the most part it doesn't make sense from a standpoint of clarity and natural language. Let's say you have model Product and you want a service object that will handle pricing on some complex criteria (geolocation, color, shipping, moonphase, etc). It would be a good candidate for a service object ProductPricingService. You wouldn't just call it Price or Pricing. First of all it's ambigious. Pricing of what? Products that you sell? Pricing you get from vendors? Pricing of gas today? And if you were to argue that this Service object could be used by many models, then you are defeating the purpose of Service Object. I'm exaggerating of course. But the whole point is to create clear and maintainable code. So while you can save some keystrokes by naming it Price, it's much more clear to another person ( and you in 5 months) if you name it ProductPricingService.
Q2
For instance let's say you have model Product. you have methods like :
If this is the only method that deals with labels you have and it's that simple than creating a Service object is an overkill. However if your method becomes complex or you find that you need multiple method for related things:
You might want to move that into a service like so:
And now just do this
Hope that clears things up a bit
hi does anybody knows or can point me to some examples if using the above with mongodb?
Welcome back, Ryan!
I really enjoy refactoring videos, they are so full of content.
I get to see how you initially thought, how you improved it, how it ended up looking, and how that still fits the same slot as before.
Another vote for refactoring-themed videos in the future, here!
You could just patch the gem up to your own liking.
F.e.:
Add a column to the tag table (rails g migration AddDescriptionToTag description:text)
Open up the class (ActsAsTaggableOn::Tag) and go from there - make the description accessible or whatever you want.
+1, and maybe a button to ask for a revised version ;-)
I did:
Then pass in the $index parameter when delete function is called:
delete function:
Hey! I have found how to Sign in with standart Devise method using "omniauth-facebook" gem:
http://stackoverflow.com/questions/16941850/sign-in-to-devise-using-omniauth-facebook
(In this tutorial, current_user var is set in application controller, but not signed in with Devise method)
Any fix for this?
Are form objects just as usable in edit actions?
This is very appropriate for apps backed by web services where the app may not have a direct database connection. I'm currently working on such an app and the API serves JSON, so building form objects that are custom for the purpose is definitely the way to go. Thanks for showing us this technique.
Ryan, definitely have to agree with some of the others that you have a very uncanny knack for always going over issues I'm working on right now. I had a simple signup form that created an account and user which works but the code isn't as "elegant" as I would like. However, I think a form object would be more complex for my simple use case.
But this gets me thinking in that fashion; instead of throwing it all into one big object because it's all "related", I'll now be thinking about ways to separate logically-related chunks of code into separate objects. Did like the fact that you could "enforce" strong parameters by individually assigning values...it's something I innately knew but didn't fully realize until you pointed it out.
Really enjoy the casts on refactoring/organizing code. They help me a lot as I tend to write it for a deadline, and then maintain it later.
true!
This is a great episode! 2 years later and still very relevant.
However, I found that using Redis as my I18n score has a noticeable performance cost - even when running on the same server as my Rails app. I wrote a very simple key-value cache gem that memoizes the translations. In my case it greatly improved my site's performance.
CachedKeyValueStore
Hey Ryan, thanks for the great tutorial.
There is one issue with auth permissions. current_user variable defined in application controller doesn't fully works with this standart Auth protection to access just a current actions in controller:
class SomeController < ApplicationController
before_filter :authenticate_user!, :except => [:action]
...
Thanks, this is really well done and helpful. I especially like that the whole process is a refactoring of old code. I've found it difficult to design loading, authorization, presenters, service_objects, etc. into the beginning of a complex project. It always seems to work better to refactor code as it becomes complex into a set of objects that work well together. Form objects must really work well with form builders and form presenters.
Just learning about Capistrano. Awesome tutorial!
Can you please explain what exactly is this line for?
sudo "ln -nfs #{current_path}/config/apache.conf /etc/apache2/sites-available/#{application}"
I can tell that the apache.conf included with the code in config directory is being symlinked in sites-available. But why is this necessary? I have already setup my apache by adding the exact same virtual host in my 'sites-enabled' directory and it works. So why copy it in sites-available, especially if apache doesn't read the config form that directory?
Yes I did. May have commented below somewhere but this is a windows specific problem because it doesn't support agent-forwarding. If you need more help I wrote everything down, but in short:
Make sure the postgresql database owner and password match the deployer username & password.
Then, I also needed to add
run "chmod +x #{release_path}/config/unicorn_init.sh"
to the symlink_config, so it would remember it has permission.
Set up the git repository on your vps, since again it won't forward from git.
Does anybody know of a way to run your js specs at the and of the suite?!