I am a beginner of RAILS.
I wrote some code , which validate if the cvs I load is correct
I have also a controller Employee (in this controller I will put validation) :
def import
if params[:csv_file]
Employee.import_from_csv(params[:csv_file], #organization, current_user)
redirect_to admin_organization_employees_path(#organization), :notice => "Your request has been accepted! We will inform you via email about the results!"
else
redirect_to :back, :notice => "Missing file"
end
end
In which place should I put Class CSV_Validator which has lots of code?? In Lib how to use it?
In your model.
Just as rule of thumb, place the bulk of your code in models.
Rails doc
Related
New web developer here, and I think I may be missing some very fundamental knowledge. Given the code
> def create
> #post = Post.new(post_params)
> if #post.save
> redirect_to #post
> else
> render "new"
> end
end
after saving the post, it redirects to show page, due to this "redirect_to #post", how can I do the same thing with "redirect_to: action => "show", :id => 5" I have to pass the ID now, how to retrieve the ID from #post object?
so only I can pass the Id to redirect page.
can I stop the compiler here, like debugger in js?
To answer your question of "I may be missing some very fundamental knowledge" yes, you might be. An object in Rails like #post is usually a database record. You can access any of it's columns in the DB by using the column name as a method:
#post.id
returns:
5 #or whatever the post id is.
If your post table has a column of "title" you can access it with
#post.title
returns:
"This is an awesome post"
I would highly recommend you view some Ruby and some Rails tutorials. Everything in Ruby is an object. Rails uses a lot of conventions so you can do things without having to write code for it, it's already there for you. When you get into Rails ActiveRecord Relations you'll see that relations expand this to give you related table information as methods. For Example:
Post.rb
...
belongs_to :user
User.rb
...
has_many :posts
Gives you methods like:
#post.user #returns the user object with all of its info
#post.user.username #returns the value of that column for that user
#post.user.posts #returns an array of Post objects that belong to the owner of that post.
Ruby has a pry-byebug gem for debugging. It's a combination REPL (Pry) and core debugger (byebug) that work very powerfully together.
Getting the id of a successfully saved ActiveRecord model is just #post.id, however the rails methods like redirect_to will take the object itself just fine, as #Beartech has mentioned, above. The documentation shows a variety of ways to use it, for convenience:
redirect_to action: "show", id: 5
redirect_to #post
redirect_to "http://www.rubyonrails.org"
redirect_to "/images/screenshot.jpg"
redirect_to posts_url
redirect_to proc { edit_post_url(#post) }
In the app I am working on, the user can get to a new form from several different places. I need to redirect them back to where they came from. I solved it by passing a parameter in the link on the view, for example
= link_to "create a new post ยป", new_user_post_path(#current_user, :return_to => 'dashboard')
then in the new action in the controller like so
if params[:return_to] == 'dashboard'
session[:return_to]= 'dashboard'
end
now I am looking at the controller. what I need to do I can achieve by being really verbose, but I'm looking for a more elegant solution. Here is what I have now
if #user_post.save
flash[:notice] = "New Post Created"
if session[:return_to] == 'dashboard'
session.delete(:return_to)
redirect_to dashboard_path and return
else
redirect_to user_hub_path(#user)
end
else
flash[:error] = "Could not save post"
redirect_to new_user_post_path(#user)
end
This does what I need but I was hoping to tidy it up a little. I started looking at 1 line enumerators to see if I could do something like this...
if #user_post.save
flash[:notice] = "New post Created"
session[:return_to] == 'dashboard' ? redirect_to "#{session.delete(:return_to)}_path" : redirect_to user_hub_path(#user)
else
flash[:error] = "Could not save post"
redirect_to new_user_post_path(#user)
end
but it really doesn't like this part....redirect_to "#{session.delete(:return_to)}_path"
any advice? Guess I'm trying to get it to redirect and delete the session in one line and this is beyond my knowledge...
This looks like a good case for using Rails' built-in :back parameter, which, according to the Rails docs here, sends the user "Back to the page that issued the request. Useful for forms that are triggered from multiple places. Short-hand for redirect_to(request.env["HTTP_REFERER"])"
You can avoid passing a return_to param, and change your controller code to:
if #user_post.save
redirect_to :back, notice: "New Post Created" and return
else
redirect_to new_user_post_path(#user), flash: { error: "Could not save post" }
end
What about using send?
send takes a message name and optional arguments and forwards that to send's receiver (http://ruby-doc.org/core-2.2.0/Object.html#method-i-send)
path = send("#{session.delete(:return_to)}_path")
redirect_to path
In this case it sends the message to the current controller instance (same as just calling the ..._path method but gives the flexibility of the dynamic call)
Please instead of using a redirect_to variable of your controller, use the Referer Header.
HTTP referer (originally a misspelling of referrer) is an HTTP header field that identifies the address of the webpage (i.e. the URI or IRI) that linked to the resource being requested
In Rails is quite simple inside a controller
redirect_to request.referer
That is more elegant and efficient, because the session cookie storage can be expensive (cache storage) and could affect your HTTP cache proxies performance.
I know there are some preset structures in i18n locale file so that Rails pulls values automatically. For example, if you want to set the default submit button text for new records:
# /config/locales/en.yml
en:
helpers:
submit:
create: "Create %{model}"
user:
create: "Sign Up"
With this set, in views the following will result:
# /app/views/things/new.html.erb
<%= f.submit %> #=> Renders a submit button reading "Create Thing"
# /app/views/users/new.html.erb
<%= f.submit %> #=> Renders a submit button reading "Sign Up"
So Rails uses a preset hierarchy for getting the submit button text for different models. (i.e., you don't have to tell it which i18n text to get when using f.submit.) I've been trying to find a way to do this with flash notices and alerts. Is there a similar preset structure for specifying default flash messages?
I know you can specify your own arbitrary structures like the following:
# /config/locales/en.yml
en:
controllers:
user_accounts:
create:
flash:
notice: "User account was successfully created."
# /app/controllers/users_controller.rb
def create
...
redirect_to root_url, notice: t('controllers.user_accounts.create.flash.notice')
...
end
But it's tedious to specify the notice: t('controllers.user_accounts.create.flash.notice') every time. Is there a way to do this so that the controller "just knows" when to grab and display the appropriate flash messages specified in the locale file? If so, what's the default YAML structure for these?
The Rails i18n guide section 4.1.4 on "lazy" lookups says:
Rails implements a convenient way to look up the locale inside views
(Emphasis theirs, and implying to me, at least, that it is restricted only to views...) However, it seems that this commit to Rails brought "lazy" lookups into controllers as well, with the key being in the form of:
"#{ controller_path.gsub('/', '.') }.#{ action_name }#{ key }"
which in your case should get you users.create.notice.
So, if you're happy with something like:
# /app/controllers/users_controller.rb
def create
...
redirect_to root_url, notice: t('.notice')
...
end
You should be able to just declare that value in:
# /config/locales/en.yml
en:
users:
create:
notice: "User account was successfully created."
I know this doesn't take you quite all the way of having a default spot where Rails would automatically go and fetch a flash notice on failure to create a user, but it's a bit better than typing out a full i18n key every time.
I think that currenly (Fall 2015) the most graceful and somewhat conventional way to implement lazy flash messages for you controllers is to use responders gem:
gem 'responders', '~> 2.1'
FlashResponder sets the flash based on the controller action and
resource status. For instance, if you do: respond_with(#post) on a
POST request and the resource #post does not contain errors, it will
automatically set the flash message to "Post was successfully
created" as long as you configure your I18n file:
flash:
actions:
create:
notice: "%{resource_name} was successfully created."
update:
notice: "%{resource_name} was successfully updated."
destroy:
notice: "%{resource_name} was successfully destroyed."
alert: "%{resource_name} could not be destroyed."
This allows to completely remove flash-related code from the controllers.
However, as you have already understood, you'll need to rewrite your controllers with their respond_with method for that:
# app/controllers/users_controller.rb
class UsersController < ApplicationController
respond_to :html, :json
def show
#user = User.find params[:id]
respond_with #user
end
end
Follow-up for #robertwbradford's comment on testing, in a Rails 4 / MiniTest functional (controller) test, you can call the translate method on the #controller instance variable:
assert_equal #controller.t('.notice'), flash[:notice]
Update : Gutted entire question with more thorough description
Ok same question with different names.
In my model, I do validate the presence of.
class QuickFact < ActiveRecord::Base
belongs_to :organization
validates_presence_of :quick_fact, :content
But if either is blank, it errors out with :
Missing template organizations/_quick_fact_fields.erb
Here's the catch. I have a nested form model with dynamically addable parts to it. As followed from here :
http://railscasts.com/episodes/197-nested-model-form-part-2
That is what generates and calls the _quick_fact_fields.erb . But that works perfectly and is located within quick_facts/_quick_fact_fields.html.haml
Update: My Controller Code
organizations_controller.rb
def update
if #organization.update_attributes(params[:organization])
..
elsif params[:organization][:quick_facts_attributes]
flash[:notice] = 'QuickFacts successfully updated.'
redirect_to organization_quick_facts_url(#organization)
else
flash[:notice] = 'Organization was successfully updated.'
redirect_to :action => 'edit'
end
else
# re-render last form
..
elsif params[:organization][:quick_facts_attributes]
render :template => "quick_facts/index"
else
render :action => 'edit'
end
end
end
It seems that you're trying to render a my_custom_field partial from one of the worker views found in app/views/worker, but apparently there's no such partial there. If you show us the code of the relevant views and controllers, it will be easier to pinpoint the exact problem.
On a side note, you could simply do validates_presence_of :name instead of defining a custom validation method to simplify your model. However, this is likely unrelated to the error you're describing and is just a general improvement suggestion.
Got it. I had two controllers.
quick_facts_controller.rb, and organizations_controller.rb
Once I deleted the update function in quick_facts_controller, it worked properly.
I am at an absolute loss as to what I am doing wrong with the following code. I am trying to implement a messaging system within my application, but want it to be handle different types of messages. In this case, I want to create a "request" message of ':message_type => 1'.
Instead of using forms as I usually have, I want to make this instance the moment the link is clicked. Here is how I have it set up in the show erb file for "user":
<%=link_to "Send friend request", :action=>"request", :controller => "messages", :id => #user.id %>
and in the controller:
def request
#message = Message.new(:sender_id => current_user.id,:user_id => params[:id],:message_type => 1)
if #message.save
flash[:notice] = 'Message was successfully created.'
redirect_to message_path(#message)
else
redirect_to message_path(#message)
end
end
This results in the following error message: undefined method `rewrite' for nil:NilClass with the trace looking like
c:/ruby/lib/ruby/gems/1.8/gems/activesupport-2.3.5/lib/active_support/whiny_nil.rb:52:in `method_missing'
c:/ruby/lib/ruby/gems/1.8/gems/actionpack-2.3.5/lib/action_controller/base.rb:634:in `url_for'
(eval):16:in `message_path'
app/controllers/messages_controller.rb:11:in `request'
I have used map.resources :messages in the routes.rb file, and done the appropriate :has_many and :belongs_to associations in the models of user and message.
EDIT: Something else to note is that the save IS succeeding, as once the root address is manually inputted into the address bar, the "flash" notice is shown saying that the save was made. Using the development console it is indeed there, so there's something messed up with the redirect.
You might want to rename the action, I am quite sure that request means something in the controller.
Why dont you rename the action from request to create, and see if it helps.
So the code will be:
In the view
<%=link_to "Send friend request", :action=>"create", :controller => "messages", :id => #user.id %>
In the controller
def create
#message = Message.new(:sender_id => current_user.id,:user_id => params[:id],:message_type => 1)
if #message.save
flash[:notice] = 'Message was successfully created.'
redirect_to message_path(#message)
else
redirect_to message_path(#message)
end
end
Check your logs more closely, and you'll probably find that your save is failing. Not sure which line is #11, but I would guess that it's in your else block, which tries to build a path for a #message object with a nil ID (it hasn't been saved).