Ruby - can't get JSON params into my controller - ruby-on-rails

Hi and thanks for taking the time to answer my question!
I have the following code in my api/ProjectController:
class Api::ProjectsController < ApplicationController
respond_to :json
def index
respond_with Project.all
end
def show
respond_with Project.find(params[:id])
end
def create
#project = Project.new(project_params)
if #project.save
redirect_to #project
else
render 'new'
end
end
end
I keep getting the following error:
undefined local variable or method `project_params' for #<Api::ProjectsController:0x00003d6d80b448>
When I change the second line in the create method to:
#project = Project.new(params[:project])
I get the following error:
ActiveModel::ForbiddenAttributesError
I am using ember and am sending JSON representation of the Project object from the front end. In both instances this is the json that's being propagated to the controller:
{"project"=>{"name"=>"asdfsdfsdf"}}
Can someone please spot where the mistake is.. I feel like I'm spending more time on this than I really should.. :/
Thank you so much and happy new year!!

You must define the project_params method that you're trying to use:
def project_params
params.require(:project).permit(:name)
end
You'll find more information and example on Rails 4 Strong parameters.

Looks like you don't have the project_params method defined in your Api::ProjectsController class. You need to add a method to your Api::ProjectsController called project_params like:
def project_params
params.require(:project).permit(:attribute)
end
Just replace the :attribute symbol with the actual attributes for the corresponding fields in your form. So if you have a 'name' and 'start_date' field for your project, then your require will look like params.require(:project).permit(:name, :start_date).

Related

Using service classes in rails application

So, I created app/services folder and then some classes inside with .call methods(I am trying to understand the logic of the services and query objects)
app/services/add_comment_to_post.rb
class AddCommentToPost
def initialize(post:, comment:)
#post = post
#comment = comment
end
def call
#post.comments.create(#comment)
#post
end
end
app/services/remove_comment_from_class.rb
class RemoveCommentFromPost
def initialize(post:, comment:)
#post = post
#comment = comment
end
def call
#post.comments.#comment.id.destroy
#post
end
end
and in the comments_controller.rb
def create
#this one works:
##post.comments.create! comment_params
AddCommentToPost.new(#post, #comment).call
redirect_to #post
def destroy
RemoveCommentFromPost.new(#post,#comment).call
redirect_to #post
Can anybody tell me what should I change to make it works, or where to look for similar examples? The posts and comments are scaffolded, and I use nested routes.
Rails.application.routes.draw do
resources :posts do
resources :comments
end
root "posts#index"
end
In general, it's helpful if you include the error you're getting from what you've tried. In this case, I've scanned the code and noticed a couple of errors that you should correct.
Your service objects define their initialize method to take keyword arguments like so:
def initialize(post:, comment:)
#post = post
#comment = comment
end
But you are initializing them by passing positional arguments like so:
AddCommentToPost.new(#post, #comment).call
You should initialize them with the expected keyword arguments like so:
AddCommentToPost.new(post: #post, comment: #comment).call
Additionally, as pasted above, your destroy method:
def destroy
RemoveCommentFromPost.new(#post,#comment).call
redirect_to #post
is missing an end.
Finally, you'll still want to check the return value of those service object calls to determine if the call succeeded or failed and handle appropriately. You are currently redirecting regardless.

rails model association author id

I'm using rails_best_practices for linting my code.
Comments belong to post, which belongs to the user.
My comments_controller.rb file looks like this
class CommentsController < ApplicationController
before_action :find_post
def create
#comment = #post.comments.create comment_params
#comment.user_id = current_user.id
redirect_to #post if #comment.save
end
private
def find_post
#post = Post.find(params[:post_id])
end
def comment_params
params.require(:comment).permit(:post_id, :body)
end
end
And I'm getting this error use model association (for #comment).
After refactoring my create method looks like this
def create
#comment = #post.comments.create(
comment_params.merge(user_id: current_user.id)
)
redirect_to #post if #comment.save
end
My question is: What is the best and correct way to do this?
Normally I'd suggest baking in any required parameters inside your controller-specific _params function. That is, do this:
def comment_params
params.require(:comment).permit(:post_id, :body).merge(
user: current_user
)
end
Then by the time it gets to your controller action you're pretty much good to go.
What I tend to do is have a build method that constructs the right object for both new and create:
def build_comment
#comment = #post.comments.build(comment_params)
end
Now this will correctly populate if you relax the require constraint on params, but it's up to you how to make that flexible. I find this consistently populates and prepares the same object for both multiple edit rounds, and the first round where you need to set some defaults.

I am getting an error says that undefined local variable or method 'blog_params' (Rails)

So I got a very basic blog app running with three links to a blog post. However, when I click on a post of my selection and edit the post and click on "update blog", I will get an error saying NameError in BlogsController#update and undefined local variable or method 'blog_params' for blogscontroller. I cannot figure out what the issue is so I would like some help to guide me through
This is what my blogs controller file looks like
class BlogsController < ApplicationController
def index
#blogs = Blog.all
end
def show
#blog = Blog.find(params[:id])
end
def new
#blog = Blog.new
end
def create
#blog = Blog.new
#blog.title = params[:blog][:title]
#blog.body = params[:blog][:body]
#blog.save
redirect_to blog_path(#blog)
end
def destroy
#blog = Blog.find(params[:id])
#blog.destroy
redirect_to blog_path(#blog)
end
def edit
#blog = Blog.find(params[:id])
end
def update
#blog = Blog.find(params[:id])
#blog.update(blog_params)
redirect_to blog_path(#blog)
end
end
def update
#blog = Blog.find(params[:id])
**#blog.update(blog_params)**
redirect_to blog_path(#blog)
end
here you are calling blog_params but you haven't defined it anywhere in your code.
See example here:
See strong params
You need to do this:
#app/controllers/blogs_controller.rb
class BlogsController < ApplicationController
def update
#blog = Blog.find params[:id]
#blog = #blog.update blog_params
end
private
def blog_params
params.require(:blog).permit(:title, :body) #-> in "permit" put the attributes of your "blog" model
end
end
The error is a standard programming issue - undeclared function.
Because you're starting - and to give you more context - the reason this is a problem is because you're calling blog_params when you run the .update method:
#blog.update blog_params
This, as mentioned by Pardeep Dhingra, is the strong params pattern introduced into Rails 4. Strong params prevents mass assignment by explicitly permitting particular attributes of your model.
Whilst your code is okay, you lack the strong params method (in your case blog_params), which Rails needs to complete the request. Adding the method will fix the issue.

ActiveModel::ForbiddenAttributesError - strong parameters

So I am following one tutorial that is obviously done in rails 3 and I am using rails 4. I get this error:
ActiveModel::ForbiddenAttributesError
With this code:
def create
#movie = Movie.create!(params[:movie])
flash[:notice] = "#{#movie.title} was successfully created."
redirect_to movies_path
end
Obviously it has something with strong param
You need to make sure that all attributes required to create a Movie are whitelisted.
Define a method like this in your controller:
private
def movie_params
params.require(:movie).permit(:title, :rating, :release_date)
end
And then pass the result of the method into create!:
def create
#movie = Movie.create!(movie_params)
# ...
end
Read more about strong parameters in the Rails documentation.

I am getting this error message after submitting a test post: param is missing or the value is empty: content?

I am trying to submit a test post through my form, and I am getting this error: param is missing or the value is empty: content. I am requiring "content" and permitting a "title". Both fields were filled out when submitting the post or "thought" in my app. I believe the problem has something to do with strong parameters. I can't find the answer anywhere else on the internet. Here is my controller.
class ThoughtsController < ApplicationController
def index
end
def new
#thought = Thought.new(params[:id])
end
def create
#thought = Thought.new(params[post_params])
#thought.save
if #thought.save
redirect_to #thought
else
render :new
end
end
private
def post_params
params.require(:content).permit(:title)
end
end
Thanks for the help.
The following should work. You propably understand the strong_parameters a bit wrong. If your thought object has :content and :title attributes, they should be listed in permit parenthesis - this will mean you allow their mass-assignment.
def create
#thought = Thought.new(post_params)
if #thought.save
redirect_to #post
else
render :new
end
end
private
def post_params
params.require(:thought).permit(:content, :title)
end

Resources