Retrieve next card(s) base on the provided parameter How can I remove the duplicated params[:next_cards]?

def index
  if params[:next_cards] # check nil
    render json: current_user.next_cards(params[:next_cards].to_i),
           status: :ok
  else
    render json: current_user.cards, status: :ok
  end
end


Inside the user.rb module,

  def next_cards(num_of_cards=nil)
    if num_of_cards
      cards.next_cards.limit(num_of_cards)
    else
      cards.next_cards
    end
  end


Inside the card.rb module,

  def self.next_cards
    joins(:meta_sm2).merge(MetaSm2.next_cards).order('RANDOM()')
  end


Inside the meta_sm2.rb model,

  scope :next_cards, -&gt; { where('next_repetition &lt;= :current_time', current_time: Time.now) }
Ok, in response to the conversation in comments, Here's my suggested first step:

  def index
    render json: cards, status: :ok
  end

  private

  def cards
    if next_cards
      current_user.next_cards(next_cards.to_i)
    else
      current_user.cards
    end
  end

  def next_cards
    params[:next_cards]
  end


the larger issue here though is that you are essentially using params[:next_cards] as a switch for what should essentially be two controller actions.  the latter being the index action of the cards controller, and the former being something along the lines of user/next_cards/:id . Possibly a next cards controller.  The show action of which could look something like

routes.rb:

resource :next_cards, only: :show


app/controllers/next_cards_controller.rb:

def show
  render json: current_user.next_cards(params[:id])
end


controllers don't have to have a 1 to 1 mapping with models. This way takes advantage of rails routing to validate that params[:id] will always be present. thereby eliminating the need for a nil check.

Obviously this could take more time as your views will need to be updated to reflect the new route. If it's a greenfield app, go ahead and do it right now. If it's an old, bloated codebase, start small with the refactor and do it in chunks.