I' ve got a controller
class Api::V1::QuestionsController < Api::V1::BaseController
authorize_resource
before_action :set_question, only:[:show]
api :GET, '/questions/id', 'This renders question by id'
def show
render json:#question
end
and a serializer
class QuestionSerializer < ActiveModel::Serializer
attributes :id, :title, :body, :created_at, :updated_at, :short_title
has_many :answers
has_many :comments
has_many :attachments
def short_title
object.title.truncate(10)
end
end
Here is a part of test
context 'answers' do
it 'included in question object' do
expect(response.body).to have_json_size(2).at_path("answers")
end
%w(id body created_at updated_at).each do |attr|
it "contains #{attr}" do
#NO UNDERSTANDING AT ALL!!!!!
expect(response.body).to be_json_eql(answers[0].send(attr.to_sym).to_json).at_path("answers/1/#{attr}")
end
end
end
The thing is that this test passes, so obviously (for unknown reasons for me) the scope differs. I am new to rails, could anybody tell me how could I set a default scope to normalize my responds, also I have to admit that In my app I have a similar not api controller and there are no problems with that scope.
Yep this is the way. I should only set order in serializer
class QuestionSerializer < ActiveModel::Serializer
attributes :id, :title, :body, :created_at, :updated_at, :short_title
has_many :answers
has_many :comments
has_many :attachments
def comments
object.comments.order(updated_at: :asc)
end
def answers
object.answers.order(updated_at: :asc)
end
def attachments
object.attachments.order(updated_at: :asc)
end
def short_title
object.title.truncate(10)
end
end
Related
I can't get rails to update my nested attributes, though regular attributes work fine. This is my structure:
unit.rb:
class Unit < ApplicationRecord
has_many :unit_skill_lists
has_many :skill_lists, through: :unit_skill_lists, inverse_of: :units, autosave: true
accepts_nested_attributes_for :skill_lists, reject_if: :all_blank, allow_destroy: true
end
unit_skill_list.rb:
class UnitSkillList < ApplicationRecord
belongs_to :unit
belongs_to :skill_list
end
skill_list.rb:
class SkillList < ApplicationRecord
has_many :unit_skill_lists
has_many :units, through: :unit_skill_lists, inverse_of: :skill_lists
end
And this is (part of) the controller:
class UnitsController < ApplicationController
def update
#unit = Unit.find(params[:id])
if #unit.update(unit_params)
redirect_to edit_unit_path(#unit), notice: "Unit updated"
else
redirect_to edit_unit_path(#unit), alert: "Unit update failed"
end
end
private
def unit_params
unit_params = params.require(:unit).permit(
...
skill_list_attributes: [:id, :name, :_destroy]
)
unit_params
end
end
The relevant rows in the form (using formtastic and cocoon):
<%= label_tag :skill_lists %>
<%= f.input :skill_lists, :as => :check_boxes, collection: SkillList.where(skill_list_type: :base), class: "inline" %>
Any idea where I'm going wrong? I have tried following all guides I could find but updating does nothing for the nested attributes.
Edit after help from Vasilisa:
This is the error when I try to update a Unit:
ActiveRecord::RecordInvalid (Validation failed: Database must exist):
This is the full unit_skill_list.rb:
class UnitSkillList < ApplicationRecord
belongs_to :unit
belongs_to :skill_list
belongs_to :database
end
There is no input field for "database". It is supposed to be set from a session variable when the unit is updated.
If you look at the server log you'll see something like skill_list_ids: [] in params hash. You don't need accepts_nested_attributes_for :skill_lists, since you don't create new SkillList on Unit create/update. Change permitted params to:
def unit_params
params.require(:unit).permit(
...
skill_list_ids: []
)
end
UPDATE
I think the best options here is to set optional parameter - belongs_to :database, optional: true. And update it in the controller manually.
def update
#unit = Unit.find(params[:id])
if #unit.update(unit_params)
#unit.skill_lists.update_all(database: session[:database])
redirect_to edit_unit_path(#unit), notice: "Unit updated"
else
redirect_to edit_unit_path(#unit), alert: "Unit update failed"
end
end
I have following Serializer
class BookSerializer < ActiveModel::Serializer
attributes :id, :name, :publisher, :author, :cover_url
has_many :chapters
end
I have two method in bookscontroller.rb file as follows:
def index
books = Book.select(:id, :name, :publisher, :publisher, :cover, :author)
if books.present?
render json: books
end
end
def show
book = Book.find_by_id params[:id]
render json: book
end
Actually everything is working fine but the problem is I want chapters records in show page not on index page, but right now query for fetching chapters are running in both action but I only want to include has_many :chapters in show action.
So Is there any way that can I use association for particular method in rails controller?
You can use different serializers for different actions. For example, remove has_many :chapters from BookSerializer and create a separate BookWithChaptersSerializer. Use it as follows:
class BookWithChaptersSerializer < ActiveModel::Serializer
attributes :id, :name, :publisher, :author, :cover_url
has_many :chapters
end
def show
book = Book.find_by_id params[:id]
render json: book, serializer: BookWithChaptersSerializer
end
So I'm having a problem with ams. I'm using Rails 5.2 and I read lots of tutorials and even when I did exactly what they showed I still have something that they don't and I didn't find answer on google.
I have model Course, Video, Quiz and Segment.
Course has many segment, segment can be video or quiz (I'm using sti).
This is how I wrote it:
app/models/course.rb
class Course < ApplicationRecord
validates :title ,presence: true
validates :author ,presence: true
has_many :videos
has_many :quizs
has_many :segments
end
app/models/segment.rb
class Segment < ApplicationRecord
belongs_to :course
end
app/models/quiz.rb
class Quiz < Segment
validates :course_id ,presence: true
validates :name ,presence: true
belongs_to :course
end
app/models/video.rb
class Video < Segment
validates :course_id ,presence: true
validates :name ,presence: true
belongs_to :course
end
app/controllers/courses_controller.rb
class CoursesController < InheritedResources::Base
def show
#course = Course.find(params[:id])
render json: #course.attributes
end
def index
#courses = Course.all
render json: #courses
end
end
app/serializers/course_serializer.rb
class CourseSerializer < ActiveModel::Serializer
attributes :title, :author
has_many :segments
end
and this is what is showed me
I have couple of problems:
I don't know where this data name come from and I don't know how to change it or hide it.
even when I request to see one course I get the created date and other stuff I didn't want, although I configured it so I only see title and author.
I want to know if I can custom the json response so I won't see the title of the relations or change it's name.
You haven't created a SegmentSerializer. By default, AMS will serialize all fields.
class SegmentSerializer < ActiveModel::Serializer
attributes :name
end
Remove the attributes method call. It returns a Hash and then your serializer is not used.
```
class CoursesController < InheritedResources::Base
def show
#course = Course.find(params[:id])
render json: #course
end
def index
#courses = Course.all
render json: #courses
end
end
```
Use the key option
has_many :segments, key: :your_key
I'm new to Ruby on Rails and currently trying to make a little test website for me.I've got an issue in my code that states an "undefined method `service_providers' for #"
The line of code which produces the error is the following:
def new
#service_provider = current_user.service_providers.build(serviceprovider_params)
end
My Database Model is Table "User" has_one "ServiceProvider" has_many "Services".
I use the rubygem "devise" for the user-model.
I've tried to transfer the idea of the micropost of the "Ruby on Rails Tutorial" (https://www.railstutorial.org/book/user_microposts) in my example app. In Listing 13.36 there's also this code because with this ruby knows the reference between the current_user and the micrrpost.
I don't have an idea why it isn't working with my code:
Model
class ServiceProvider < ApplicationRecord
belongs_to :user
has_many :service
validates :name, presence: true
validates :street, presence: true
validates :plz, presence: true
validates :location, presence: true
validates :user_id, presence: true
end
Controller
class ServiceProvidersController < ApplicationController
before_action :set_serviceprovider, only: [:show, :edit, :update]
before_action :authenticate_user!
def index
end
def show
end
def new
#service_provider = current_user.service_providers.build(serviceprovider_params)
end
def create
#service_provider = current_user.service_provider.build(serviceprovider_params)
if #service_provider.save
redirect_to #service_provider, notice: "Gespeichert"
else
render :new
end
end
def edit
end
def update
end
private
def set_serviceprovider
#service_provider = Service_Provider.find(params [:id])
end
def serviceprovider_params
params.require(:service_provider).permit(:name, :street, :plz, :location)
end
end
ServiceProvider-Helper
module ServiceProvidersHelper
def current_service_provider
#current_service_provider = service_provider.user_id.find(current_user.id)
end
end
If there's some coding missing which you need for your help, please ask. I'm a newbie in coding with ruby, but i think taht must be the relevant parts of the code which is involved.
Thanks for help.
If you have has_one association then you need to use build_ASSOCIATION_NAME so in this case, it will be build_service_provider
#service_provider = current_user.build_service_provider(serviceprovider_params)
Also, I think you need to take a look at this association
class ServiceProvider < ApplicationRecord
belongs_to :user
has_many :service
If you are building an association with has_many then the class name should be plural.
Change it to
has_many :services
There is an association with course and course instance. When I visit the url /courses/1/course_instances/new, I get the error below.
This is the error I got:
No route matches {:controller=>"course_instances", :course_id=>nil}
Models
Course:
class Course < ActiveRecord::Base
attr_accessible :code, :credits, :description, :hours, :id, :name, :pass_mark
has_many :course_instances, :dependent => :destroy
accepts_nested_attributes_for :course_instances
end
Course Instance
class CourseInstance < ActiveRecord::Base
attr_accessible :end_date, :id, :start_date
belongs_to :course
end
Routes
Sis::Application.routes.draw do
resources :courses do
resources :course_instances
end
root :to => 'home#index'
end
Course Instance Controller
class CourseInstancesController < ApplicationController
before_filter :find_course
def new
#course_instance = #course.course_instances.build
respond_to do |format|
format.html
end
end
def find_course
#course = Course.find(params[:course_id])
end
end
new.html.erb
<%= form_for ([#course, #course_instance]) do |f| %>
---- excluded for brevity ----
Rake Routes
new_course_course_instance GET /courses/:course_id/course_instances/new(.:format) course_instances#new
Am not sure what I did but it started to work. I tried backtracking to recreate the error however I have been unsuccessful so far. Weird! Thanks for the help from everyone!