for a university project I'm looking to make some changes to the Rails scaffolding mechanism. Mainly, I want to know where controller scaffold code is generated.
When looking at where the code is generated I found what looked like the appropriate bits here: https://github.com/rails/rails/blob/master/railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb.tt
However, after changing it, it doesn't seem to make a difference. I tried both rails g scaffold .... and rails g scaffold_controller ....
I also noticed that the code that I end up with looks different from what I would expect from the template.
template:
# PATCH/PUT <%= route_url %>/1
def update
if #<%= orm_instance.update("#{singular_table_name}_params") %>
redirect_to <%= redirect_resource_name %>, notice: <%= "'#{human_name} was successfully updated.'" %>
else
render :edit
end
end
reality (dogs_controller.rb):
# PATCH/PUT /dogs/1
# PATCH/PUT /dogs/1.json
def update
respond_to do |format|
if #dog.update(dog_params)
format.html { redirect_to #dog, notice: 'Dog was successfully updated.' }
format.json { render :show, status: :ok, location: #dog }
else
format.html { render :edit }
format.json { render json: #dog.errors, status: :unprocessable_entity }
end
end
end
So mainly the generated code also responds to json requests, while the template does not look like it respects that.
The scaffolding console output also claims to invoke scaffold_controller.
Then there's also the code here: https://github.com/rails/rails/blob/master/railties/lib/rails/generators/rails/controller/templates/controller.rb.tt but that is even more bare bones.
Long story short, am I doing something wrong or where is the controller code for scaffolding generated.
FYI I cloned rails at commit a1f9fe8bdd4e6c4e20fbda424c0ecf2f31fabd30 and branched of from there, so fairly recently.
Related
In my Rails project, I ran:
rails generate scaffold car
which successfully created all of the necessary files and directories for the application. This includes the standard application.html.erb layout file, as well as the app/views/cars directory that includes more standard html.erb files (index, show, ETC.)
In addition, my cars route is in place in config/routes.rb.
My next command is rails server, which is also successful.
When I open my browser and go to localhost:3000, the welcome page for ruby on rails pops up as normal. I'm expecting that when I go to localhost:3000/cars, I'll see the html rendered from app/views/cars/index.html.erb. If not, I at least expect that it will default to application.html.erb.
Instead, I am repeatedly receiving the following:
>ActionController::UnknownFormat in CarsController#index
>CarsController#index is missing a template for this request format and variant. request.formats: ["text/html"] request.variant: []
My controller class looks like this:
class CarsController < ApplicationController
before_action :set_car, only: [:show, :edit, :update, :destroy]
# GET /cars
# GET /cars.json
def index
#cars = Car.all
end
# GET /cars/1
# GET /cars/1.json
def show
end
# GET /cars/new
def new
#car = Car.new
end
# GET /cars/1/edit
def edit
end
# POST /cars
# POST /cars.json
def create
#car = Car.new(car_params)
respond_to do |format|
if #car.save
format.html { redirect_to #car, notice: 'Car was successfully created.' }
format.json { render :show, status: :created, location: #car }
else
format.html { render :new }
format.json { render json: #car.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /cars/1
# PATCH/PUT /cars/1.json
def update
respond_to do |format|
if #car.update(car_params)
format.html { redirect_to #car, notice: 'Car was successfully updated.' }
format.json { render :show, status: :ok, location: #car }
else
format.html { render :edit }
format.json { render json: #car.errors, status: :unprocessable_entity }
end
end
end
# DELETE /cars/1
# DELETE /cars/1.json
def destroy
#car.destroy
respond_to do |format|
format.html { redirect_to cars_url, notice: 'Car was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_car
#car = Car.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def car_params
params.fetch(:car, {})
end
end
I'd greatly appreciate any insight into this issue. I've followed every bit of advice I've seen on the internet regarding layouts, controllers, and views, and I'm having no luck.
Thanks in advance!
Thanks to everyone who was trying to answer my question! It was a stumper, but I've discovered the problem:
After uninstalling and reinstalling rails a few times, I created a dummy rails project and generated a new scaffold "car." Upon running rails server and loading up localhost:3000/cars, the default layout was rendered as normal. Thinking that reinstalling rails had solved it, I then linked the dummy project to a remote github repository.
At this point, running rails server and loading localhost:3000/cars showed me the same error message as before. This made me believe that something about the remote repo was messing up my project, so I googled around for this error message and github.
I stumbled upon the following link which ultimately answered my question:
https://github.com/rails/rails/issues/18660
Turns out, one of the directories in my root path was capitalized, and that was throwing rails off right away. As soon as I renamed the capitalized directory to all lowercase, the app ran flawlessly.
I'm frustrated by ruby on rails' extremely opinionated conventions, and especially since this project is almost a week late due to such an esoteric mistake. But I'm over the moon to have it running smoothly now and I hope this may help someone else in the future.
Thanks again all!
I've just started to play with Rails applications and I'm trying to use Ajax on a form, but I don't know how to catch the status code inside a js.erb file. I'm following this tutorial: http://guides.rubyonrails.org/working_with_javascript_in_rails.html
On my Users controller I have a code for my update method:
respond_to do |format|
if #user.save
format.html { redirect_to #user, notice: 'User was successfully created.' }
format.js {}
format.json { render json: #user, status: :created, location: #user}
else
format.html { render action: 'edit' }
format.js {}
format.json { render json: #user, status: :unprocessable_entity }
logger.debug #user.response_errors
end
end
I've created a update.js.erb file inside my views/users/ folder and is very easy to debug the #user var, but I don't know how to get the status code setted on my method.
Sorry if it's a stupid question, but I'm new with rails and I'm trying to follow all the frameworks concepts to the letter and I don't know the best pratices to create responses to Ajax requests.
What I'm trying to achieve is something like this:
#on my update.js.erb
if( status == 'created' ) {
alert( 'Ok, created' )
} else {
alert( 'Something wrong happened' )
}
I appreciate any help.
Option 1: Check Validity Inside update.js.erb
This is the option that I recommend in most cases.
update.js.erb is an ERB template whose result is a JavaScript code to evaluate on the client. In this case, you can make it look like:
<% if #user.valid? %>
alert('Ok, created');
<% else %>
alert('Something wrong happened');
<% end %>
The decision which alert to displays happens server-side. The client receives either:
alert('Ok, create');
or
alert('Something wrong happened');
depending on the status of #user.
Option 2: Two separate js.erb files
You can split your update.js.erb into two files. update.js.erb should contain the happy path code:
alert('Ok, create');
update-error.js.erb should contain some error handling:
alert('Something wrong happened');
Then you decide which one to display in your controller:
respond_to do |format|
if #user.save
# ...
format.js {}
# ...
else
# ...
format.js { render 'update-error' }
# ...
end
end
I would try to do:
format.js {render json: {#user, status: :created, location: #user}}
I have a Rails 3.2 app that uses session store in the controllers to get the user back to the screen they were previously on.
It's been working fine for over a year. All of a sudden, the production version on Heroku, has started having issues. The user is looking at a worequest and clicks on the following in order to add a comment.
<%= link_to 'New Comment', new_comment_path(:worequest_id => #worequest.id), :class => 'btn btn-primary' %>
This is the code I use:
def new
#comment = Comment.new
#comment.build_attachment
#worequest = params[:worequest_id]
session[:return_to] ||= request.referer
respond_to do |format|
format.html # new.html.erb
format.json { render json: #comment }
end
end
# POST /comments
# POST /comments.json
def create
#comment = Comment.new(params[:comment])
respond_to do |format|
if #comment.save
if session[:return_to] != nil
format.html { redirect_to session.delete(:return_to), notice: 'Comment was successfully created.' }
format.json { render json: #comment, comment: :created, location: #comment }
else
format.html { redirect_to :back, notice: 'Comment was successfully created.' }
format.json { render json: #comment, comment: :created, location: #comment }
end
else
format.html { render action: "new" }
format.json { render json: #comment.errors, status: :unprocessable_entity }
end
end
end
In development and staging (on Heroku), the user goes back to the worequest after entering a new comment.
Now in Production, the url looks like this:
mywebsite/comments instead of mywebsite/worequests/639
I'm not even sure where the session[:return_to] gets stored. Therefore, I'm having trouble debugging the issue.
Thanks for your help!!
Are you able to replicate this behavior 100% of the time, or just seeing it sometimes in your log?
It looks like someone is getting to comments#new from /comments (comments#index). Is there a route to /comments?
Run rake routes to see all your routes.
If there is a route to comments#index, and there's no reason for it to be exposed because you only intend for people to post comments from within the context of a specific article, consider removing it the comments#index route.
Also, one thing to consider, request.referrer is not always available. It's sent by the client who may choose not to send it (e.g. certain privacy extensions remove this header).
I am using almost the code from the regular scaffold. The only change is the 4.times block where I make 4 answer objects on the question. The reason is that I have the corresponding input fields in the view. Now, if the validation fails it renders the new.html.erb again, however after what I have been reading it does not invoke the "new" action again. However I am depending on the 4.times block because otherwise the loop in the view have no answers to loop through. How do I fix this? I tried redirecting but then the error messages disappered.
New action
def new
#question = Question.new
4.times do
#question.answers.build
end
respond_to do |format|
format.html # new.html.erb
format.json { render json: #question }
end
end
Create action
def create
#question = Question.new(params[:question])
respond_to do |format|
if #question.save
format.html { redirect_to #question, notice: 'Question was successfully created.' }
format.json { render json: #question, status: :created, location: #question }
else
format.html { render action: "new" }
format.json { render json: #question.errors, status: :unprocessable_entity }
end
end
end
Exactly as your title suggests: render does just render (the template belonging to) the action and not perform the action itself.
To get your prebuilt answers rendered again in a failed create call, I suggest removing the :reject_if condition from the nested attributes setup. This way, empty submitted answers are preserved. To prevent them from being written to the database, just add regular validations to the Question model...
What you need to look at is the #question in your create action. In theory it should contain the 4 newly built answers so redisplaying the form would also contain these.
If they are not written you may have to look at the accepts_nested_attributes_for to make sure it gets deserialized correctly from the request.
I have a fairly standard controller with a create method and some validations.
def create
#type = Type.new(params[:type])
respond_to do |format|
if #type.save
format.html { redirect_to types_path, notice: 'Type was successfully created.' }
format.json { render json: #type, status: :created, location: #type }
else
format.html { render action: "new" }
format.json { render json: #type.errors, status: :unprocessable_entity }
end
end
end
The problem is that when a validation fails, I get the errorMissing template ontology/types/create, as if the render action: "new" weren't there. If I replace it with a redirect_to then it works as expected, but then it seems I can't pass the form errors along.
I know that there is a #type instance (with #type.errors) from the original call of new, and throwing it just before the render call confirms this.
The same thing is happening when a validation fails on update It seems like the render call is just being ignored!
NOTE: my routing structure is a little unconventional, but I see not reason why this should be related.
This looks very similar: Path defined in controller and action is getting ignored, Ruby on Rails
Based on the answer to that question, I'm guessing that something is missing that is needed for rendering the new view, and as a result rails is just skipping the render call altogether and rendering create.
Can you show the new controller action and view?